﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using Bling.Util;
using Bling.DSL;
using Bling.Core;
using Bling.Vecs;


namespace Bling.Core {
  using Bling.Core;

  public abstract partial class UnaryOperator<A, B, CNT> : Ops.Operator<A, B, CNT> where CNT : UnaryOperator<A, B, CNT> {
    public abstract string Name { get; }
    public override SmartString Format(SmartString s) {
      if (this is ICallOperator) return Name + "(" + s + ")";
      else if (this is ISyntaxOperator) return Name + s;
      else return base.Format(s);
    }
  }
  public abstract partial class BinaryOperator<A, B, C, CNT> : Ops.Operator<A, B, C, CNT> where CNT : BinaryOperator<A, B, C, CNT> {
    public abstract string Name { get; }
    public override SmartString Format(SmartString argA, SmartString argB) {
      if (this is ICallOperator) return Name + "(" + argA + ", " + argB + ")";
      else if (this is ISyntaxOperator) return argA + Name + argB;
      else return base.Format(argA, argB);
    }
  }
  public abstract partial class TrinaryOperator<A, B, C, D, CNT> : Ops.Operator<A, B, C, D, CNT> where CNT : TrinaryOperator<A, B, C, D, CNT> {
    public abstract string Name { get; }
    public override SmartString Format(SmartString argA, SmartString argB, SmartString argC) {
      if (this is ICallOperator)
        return Name + "(" + argA + ", " + argB + ", " + argC + ")";
      else return base.Format(argA, argB, argC);
    }
  }
  public partial interface ICoreValue<BRAND> : ICoreValue, IConditionTarget<BRAND>, ICanTable<BRAND> where BRAND : ICoreValue<BRAND> {
    BoolBl Equal(BRAND Other);
  }
  public partial interface ICanTable<SELF> {
    SELF Table(Core.IntBl Index, SELF[] Cases);
  }
  public abstract partial class Brand<BRAND> : Brand, ICanBind<BRAND>, ICanMakeParam<BRAND> where BRAND : Brand<BRAND> {
    public abstract BRAND Table(Core.IntBl Index, BRAND[] Cases);
    public abstract BRAND ChooseA(Core.BoolBl Test, BRAND Other);
    public abstract BoolBl Equal(BRAND Other);
    
  }
  public interface ITableExpr : IExpr {
    Expr<int> Index { get; }
    Expr[] Values { get; }
  }
  public interface ITableExpr<T> : ITableExpr, IExpr<T> {
    new Expr<T>[] Values { get; }
  }
  public partial class TableExpr<T> : Expr<T>, ITableExpr<T> {
    public readonly Expr<int> Index;
    public readonly Expr<T>[] Values;

    Expr<int> ITableExpr.Index { get { return this.Index; } }
    Expr[] ITableExpr.Values { get { return this.Values; } }
    Expr<T>[] ITableExpr<T>.Values { get { return this.Values; } }

    public TableExpr(Expr<T>[] Values, Expr<int> Index) {
      this.Values = Values; this.Index = Index;
    }
    public override bool Solve(IAssign P, Expr<T> other) {
      if (P is NowAssign<Action>) { // special case....
        var txt = (NowAssign<Action>)P;
        var Results = new Action[Values.Length][];
        for (int i = 0; i < Values.Length; i++) {
          var txt0 = new NowAssign<Action>(txt.Arguments);
          if (!Values[i].Solve(txt0, other)) return base.Solve(P, other);
          Results[i] = txt0.Results.ToArray();
        }
        var IndexF = Index.AsFunc;
        Action a = () => {
          foreach (var aa in Results[IndexF()]) aa();
        };
        txt.Results.Add(a);
        return true;
      }
      return base.Solve(P, other);
    }

    public bool BodyConstant {
      get {
        var result = true;
        for (int i = 0; i < Values.Length && result; i++)
          result = result && Values[i].IsConstant;
        return result;
      }
    }

    public override bool IsConstant {
      get {
        return Index.IsConstant && BodyConstant;
      }
    }
    protected override Eval<EVAL>.Info<T> Eval<EVAL>(Eval<EVAL> txt) {
      if (txt is ITableEval<EVAL>)
        return ((ITableEval<EVAL>)txt).Table<T>(Values, Index);
      if (txt is TranslateEval<EVAL>) {
        var Index0 = ((TranslateEval<EVAL>)txt).Translate(this.Index);
        var Values0 = new Expr<T>[Values.Length];
        for (int i = 0; i < Values.Length; i++) Values0[i] = ((TranslateEval<EVAL>)txt).Translate(Values[i]);
        return ((TranslateEval<EVAL>)txt).NoTranslation(new TableExpr<T>(Values0, Index0));
      }
      /*
      Expr<T> result = new Constant<T>();
      for (int i = 0; i < Values.Length; i++) {

        result = ValueOperators<T>.Condition.Instance.Make(
          ValueOperators<int>.Equal.Instance.Make(Index, new Constant<int>(i)), Values[i], result);
      }
      return txt.DoEval(result);
       */
      throw new NotSupportedException();
    }
    public override Expr<T> Transform(Transformer t) {
      var Index = t.Transform(this.Index);
      var Values = new Expr<T>[this.Values.Length];
      for (int i = 0; i < Values.Length; i++) {
        Values[i] = t.Transform(this.Values[i]);
      }
      if (Index is Constant<int>) {
        var idx = (((Constant<int>)Index)).Value;
        if (Values[idx] is Constant<T>) return ((Constant<T>)Values[idx]).Value;
        else return Values[idx];
      } else return new TableExpr<T>(Values, Index);
    }
    protected override string ToString1() {
      return Values.ToList().ToString() + "[" + Index + "]";
    }
    protected override int GetHashCode0() {
      var hc = Index.GetHashCode();
      foreach (var e in Values) hc += e.GetHashCode();
      return hc;
    }
    protected override bool Equals0(Expr<T> obj) {
      if (obj is TableExpr<T>) {
        var v = (TableExpr<T>)obj;
        if (!Index.Equals(v.Index)) return false;
        if (Values.Length != v.Values.Length) return false;
        for (int i = 0; i < Values.Length; i++) if (!Values[i].Equals(v.Values[i])) return false;
        return true;
      } else return base.Equals0(obj);
    }
  }
  public partial class TableExpr2<S> : Expr<S>, ITableExpr<S> {
    public readonly Expr<int> Index;
    public readonly S[] Values;
    public TableExpr2(S[] Values, Expr<int> Index) {
      this.Values = Values; this.Index = Index;
    }
    Expr<int> ITableExpr.Index { get { return this.Index; } }
    Expr[] ITableExpr.Values {
      get {
        var ret = new Expr<S>[Values.Length];
        for (int i = 0; i < Values.Length; i++) ret[i] = new Constant<S>(Values[i]);
        return ret;
      }
    }
    Expr<S>[] ITableExpr<S>.Values {
      get {
        var ret = new Expr<S>[Values.Length];
        for (int i = 0; i < Values.Length; i++) ret[i] = new Constant<S>(Values[i]);
        return ret;
      }
    }
    protected override Eval<EVAL>.Info<S> Eval<EVAL>(Eval<EVAL> txt) {


      if (txt is ITableEval<EVAL>)
        return ((ITableEval<EVAL>)txt).Table<S>(Values, Index);
      if (txt is TranslateEval<EVAL>) {
        var Index0 = ((TranslateEval<EVAL>)txt).Translate(Index);
        return ((TranslateEval<EVAL>)txt).NoTranslation(new TableExpr2<S>(Values, Index0));
      }
      throw new NotSupportedException();
    }
    public override Expr<S> Transform(Transformer t) {
      var Index = t.Transform(this.Index);
      if (Index is Constant<int>) {
        var idx = (((Constant<int>)Index)).Value;
        if (Values[idx] is Constant<S>) return ((Constant<S>)Values[idx]).Value;
        else return Values[idx];
      } else return new TableExpr2<S>(Values, Index);
    }
    protected override string ToString1() {
      return Values.ToList().ToString() + "[" + Index + "]";
    }
    protected override int GetHashCode0() {
      var hc = Index.GetHashCode() + Values.GetHashCode();
      return hc;
    }
    protected override bool Equals0(Expr<S> obj) {
      if (obj is TableExpr2<S>) {
        var v = (TableExpr2<S>)obj;
        if (!Index.Equals(v.Index)) return false;
        if (!object.ReferenceEquals(Values, v.Values)) return false;
        return true;
      } else return base.Equals0(obj);
    }
  }

  public abstract partial class Brand<T, BRAND> : Brand<BRAND>, IBrandT<T>, IExtends<BRAND, ObjectBl>, IBrand<T, BRAND> where BRAND : Brand<T, BRAND> {
    public virtual bool CanReallyTable { get { return true; } }
    public virtual BRAND0 Remake<BRAND0>(Func<BRAND, BRAND0> F) where BRAND0 : Brand<BRAND0> {
      if (!CanReallyTable && Provider is ITableExpr<T>) {
        var e = (ITableExpr<T>) Provider;
        var Values = new BRAND0[e.Values.Length];
        for (int i = 0; i < Values.Length; i++) Values[i] = F(ToBrand(e.Values[i]));
        return Values.Table(e.Index);
      } else return F(this);
    }

    public override BRAND Table(IntBl Index, BRAND[] Values) {
      var Es = new Expr<T>[Values.Length];
      bool IsObviousConstant = true;
      for (int i = 0; i < Values.Length; i++) {
        Es[i] = Values[i].Provider;
        IsObviousConstant = IsObviousConstant && Es[i].IsObviousConstant;
      }
      if (IsObviousConstant) {
        var Fs = new T[Values.Length];
        for (int i = 0; i < Values.Length; i++)
          Fs[i] = Values[i].CurrentValue;
        return ToBrand((new TableExpr2<T>(Fs, Index.Provider)));
      } else return ToBrand((new TableExpr<T>(Es, Index.Provider)));
    }


    public override BoolBl Equal(BRAND opB) {
      if (Provider.Equals(opB.Provider)) return true;
      return EqualOp.Instance.Make(Provider, opB.Provider);
    }
    public virtual BoolBl NotEqual(BRAND opB) {
      if (Provider.Equals(opB.Provider)) return false;
      return NotEqualOp.Instance.Make(Provider, opB.Provider);
    }

    public static BoolBl operator ==(Brand<T, BRAND> opA, BRAND opB) {
      return opA.Equal(opB);
    }
    public static BoolBl operator !=(Brand<T, BRAND> opA, BRAND opB) {
      return opA.NotEqual(opB);
    }


    /*
    public static BRAND Table<S>(S[] Values, IntBl Index, Func<Expr<S>,Expr<T>> F) {
      return ToBrand(F(new TableExpr2<S>(Values, Index.Underlying)));
    }*/



    public partial class ConditionAOp : TrinaryOperator<bool, T, T, T, ConditionAOp> {
      public new static readonly ConditionAOp Instance = new ConditionAOp();
      private ConditionAOp() {}
      public override Eval<EVAL>.Info<T> Eval<EVAL>(Bling.Ops.Operation<bool, T, T, T> op, Eval<EVAL> txt) {
        if (txt is Ops.IConditionEval<EVAL>)
          return ((Ops.IConditionEval<EVAL>)txt).Condition(op.ArgA, op.ArgB, op.ArgC);
        return base.Eval<EVAL>(op, txt);
      }
      public override SmartString Format(SmartString argA, SmartString argB, SmartString argC) {
        return "if (" + argA + ") " + argB + " else " + argC;
      }
      public override string Name {
        get { return "?"; }
      }
    }
    public override BRAND ChooseA(Core.BoolBl Test, BRAND Other) {
      return ToBrand(ConditionAOp.Instance.Make(Test, this, Other));
    }


    public abstract partial class EqualityOp<CNT> : BinaryOperator<T,T,bool,CNT>, ISyntaxOperator where CNT : EqualityOp<CNT> { }
    public partial class EqualOp : EqualityOp<EqualOp> {
      public new static EqualOp Instance = new EqualOp();
      private EqualOp() { }
      public override string Name { get { return "=="; } }
    }
    public partial class NotEqualOp : EqualityOp<NotEqualOp> {
      public new static NotEqualOp Instance = new NotEqualOp();
      private NotEqualOp() { }
      public override string Name { get { return "!="; } }
    }

  }

}

namespace Bling.Core {
  interface ICallOperator { }
  interface IMathLinqOperator : ICallOperator { }
  interface ITypeLinqOperator : ICallOperator { }
  interface INoLinqOperator : ICallOperator { }
  interface ICustomLinqCallOperator : ICallOperator {
    Type From { get; }
    string Name { get; }
  }
  interface INoShaderOperator { }
  interface ICustomShaderCallOperator {
    string ShaderName { get; }
  }

  interface ISyntaxOperator { }

  public interface IValueBrand { }
  public interface IValueBrand<BRAND> : IValueBrand where BRAND : IValueBrand<BRAND> {
  }

  /// <summary>
  /// Root of all value brands.
  /// </summary>
  public abstract partial class ValueBrand<T, BRAND> : Brand<T, BRAND>, IValueBrand<BRAND> where BRAND : ValueBrand<T,BRAND> {
    public ValueBrand(Expr<T> Underlying) : base(Underlying) { }
    public ValueBrand() : base() { }

    protected Func<BRAND, bool> VerifyRHS = (value) => true;
    protected Func<BRAND, BRAND> AsRHS0 = (value) => value;
    protected string RHSFail = "RHS constraint violated";

    public override BRAND CopyMetaTo(BRAND Other) {
      Other = base.CopyMetaTo(Other);
      Other.VerifyRHS = VerifyRHS;
      Other.AsRHS0 = AsRHS0;
      Other.RHSFail = RHSFail;
      return Other;
    }

    protected internal override BRAND AsRHS(BRAND Other) {
        var ret = AsRHS0(base.AsRHS(Other));
        // horrible error message.
        if (!VerifyRHS(ret)) throw new NotSupportedException(RHSFail);
        return ret;
    }

    public abstract partial class Operator<S, CNT> : Ops.Operator<T, S, CNT> where CNT : Operator<S, CNT> {}
    public abstract partial class Operator<S, U, CNT> : Ops.Operator<T, S, U, CNT> where CNT : Operator<S, U, CNT> {}
    public abstract partial class Operator<S, U, V, CNT> : Ops.Operator<T, S, U, V, CNT> where CNT : Operator<S, U, V, CNT> {}

  }
  public interface IValueBrandKD<K, D> : IValueBrand where D : Dim<D> { }

  public abstract partial class BaseValueBrand<T, BRAND, K, D> : ValueBrand<T, BRAND>, IValueBrandKD<K,D>
    where BRAND : ValueBrand<T, BRAND, K, D>
    where D : Dim<D> {
    public BaseValueBrand(Expr<T> Underlying) : base(Underlying) { }
    public BaseValueBrand(Expr<IVec<K,D>> Underlying) : this(Convert(Underlying)) { }
    public BaseValueBrand() : base() { }
    public static readonly Func<Expr<IVec<K,D>>, BRAND> ToBrandD;

    public Expr<IVec<K, D>> UnderlyingD {
      get {
        if (Provider is Expr<IVec<K, D>>) return (Expr<IVec<K, D>>)(object)Provider;
        (Dim<D>.Count == 1).Assert();
        (typeof(T) == typeof(K)).Assert();
        return Composite<K, D>.Make((Expr<K>)(object)Provider);
      }
    }
    public partial class CombineOp<E, F> : BinaryOperator<IVec<K, E>, IVec<K, F>, IVec<K, D>, CombineOp<E, F>>, INoLinqOperator, INoShaderOperator where E : Dim<E> where F : Dim<F> {
      public new static readonly CombineOp<E, F> Instance = new CombineOp<E, F>();
      private CombineOp() { }
      static CombineOp() {
        (Dim<E>.Count + Dim<F>.Count == Dim<D>.Count).Assert();
      }
      public override bool IsCheap {
        get { return true; }
      }
      public override string Name { get { return "Combine"; } }
      public override Expr<IVec<K, D>> Expand(Expr<IVec<K, E>> argA, Expr<IVec<K, F>> argB) {
        var Es = new Expr<K>[Dim<D>.Count];
        for (int i = 0; i < Dim<E>.Count; i++)
          Es[i] = AccessExpr<K, E>.Make(argA, i);
        for (int i = 0; i < Dim<F>.Count; i++)
          Es[Dim<E>.Count + i] = AccessExpr<K, F>.Make(argB, i);
        return Composite<K, D>.Make(Es);
      }
    }


    static BaseValueBrand() {
      var c = typeof(BRAND).GetConstructor(new Type[1] { typeof(Expr<IVec<K,D>>) });
      (c != null).Assert();
      ToBrandD = e => (BRAND)c.Invoke(new object[] { e });

      var Es = new Expr<K>[Dim<D>.Count];
      for (int i = 0; i < Es.Length; i++) Es[i] = new Constant<K>(default(K));
      ValueBrand<T,BRAND>.Default = ToBrandD(Composite<K, D>.Make(Es));
    }
    private static Expr<T> Convert(Expr<IVec<K, D>> Underlying) {
      if (Underlying is Expr<T>) return (Expr<T>)(object)Underlying;
      (Dim<D>.Count == 1).Assert();
      (typeof(T) == typeof(K)).Assert();
      return (Expr<T>)(object)AccessExpr<K, D>.Make(Underlying, 0);
    }

  }
  public abstract partial class ValueBrand<T, BRAND, K, D> : BaseValueBrand<T, BRAND, K, D>
    where BRAND : ValueBrand<T, BRAND, K, D>
    where D : Dim<D> {
    public ValueBrand(Expr<T> Underlying) : base(Underlying) { }
    public ValueBrand(Expr<IVec<K,D>> Underlying) : base(Underlying) { }
    public ValueBrand() : base() { }
    public static implicit operator Expr<IVec<K, D>>(ValueBrand<T, BRAND, K, D> value) { return value.UnderlyingD; }
  }
  public interface IValueBrand<BRAND, SCALAR> : IValueBrand<BRAND>
    where BRAND : IValueBrand<BRAND, SCALAR>
    where SCALAR : IValueBrand<SCALAR, SCALAR> {
  }

  public interface IValueBrand<BRAND,D,SCALAR> : IValueBrand<BRAND,SCALAR> where BRAND : IValueBrand<BRAND,D,SCALAR> where D : Dim<D> where SCALAR : IValueBrand<SCALAR,D1,SCALAR> {
    BRAND ChooseB<BBRAND>(BoolBl<D,BBRAND> Test, BRAND Other) where BBRAND : BoolBl<D,BBRAND>;
  }


  public interface IHasX<SCALAR> where SCALAR : IValueBrand<SCALAR> {
    SCALAR X { get; }
  }
  public interface IHasX<K, SCALAR> : IHasX<SCALAR>, IValueBrandKS<K, SCALAR> where SCALAR : ValueBrand<K, SCALAR, K, D1, SCALAR> { }

  public interface IHasXY<SCALAR> : IHasX<SCALAR> where SCALAR : IValueBrand<SCALAR> {
    SCALAR Y { get; }
  }
  public interface IHasXY<K, SCALAR> : IHasXY<SCALAR>, IHasX<K, SCALAR>
    where SCALAR : ValueBrand<K, SCALAR, K, D1, SCALAR>
    { }
  public interface IHasXYZ<SCALAR> : IHasXY<SCALAR> where SCALAR : IValueBrand<SCALAR> {
    SCALAR Z { get; }
  }
  public interface IHasXYZ<K, SCALAR> : IHasXYZ<SCALAR>, IHasXY<K, SCALAR> where SCALAR : ValueBrand<K, SCALAR, K, D1, SCALAR> { }
  public interface IHasXYZW<SCALAR> : IHasXYZ<SCALAR> where SCALAR : IValueBrand<SCALAR> {
    SCALAR W { get; }
  }
  public interface IHasXYZW<K, SCALAR> : IHasXYZW<SCALAR>, IHasXYZ<K, SCALAR> where SCALAR : ValueBrand<K, SCALAR, K, D1, SCALAR> { }


  public partial interface IValueBrandKS<K, SCALAR> where SCALAR : ValueBrand<K, SCALAR, K, D1, SCALAR> {}
  public abstract partial class BaseValueBrand<T, BRAND, K, D, SCALAR> : ValueBrand<T, BRAND, K, D>, IValueBrand<BRAND, D, SCALAR>, IValueBrandKS<K,SCALAR>
    where BRAND : ValueBrand<T, BRAND, K, D, SCALAR>
    where D : Dim<D>
    where SCALAR : ValueBrand<K, SCALAR, K, D1, SCALAR> {
    public BaseValueBrand(Expr<T> Underlying) : base(Underlying) { }
    public BaseValueBrand(Expr<IVec<K, D>> Underlying) : base(Underlying) { }
    public BaseValueBrand(SCALAR[] Es) : this(Convert(Es)) { }
    public BaseValueBrand() : base() { }

    public SCALAR X { get { return this[0]; } set { X.Bind = value; } }
    public SCALAR Y { get { return this[1]; } set { X.Bind = value; } }
    public SCALAR Z { get { return this[2]; } set { X.Bind = value; } }
    public SCALAR W { get { return this[3]; } set { X.Bind = value; } }

    private static Expr<IVec<K, D>> Convert(SCALAR[] Es) {
      (Es.Length == Dim<D>.Count).Assert();
      var Es0 = new Expr<K>[Es.Length];
      for (int i = 0; i < Es.Length; i++)
        Es0[i] = Es[i];
      return Composite<K, D>.Make(Es0);
    }
    public static BRAND Repeat(Func<K> s) {
      return Repeat(ValueBrand<K, SCALAR, K, D1, SCALAR>.ToBrand(new Constant<K>(s())));
    }
    public static BRAND Repeat(K s) {
      (ValueBrand<K, SCALAR, K, D1, SCALAR>.ToBrand != null).Assert();
      return Repeat(ValueBrand<K, SCALAR, K, D1, SCALAR>.ToBrand(new Constant<K>(s)));
    }
    public static BRAND Repeat(SCALAR s) {
      var Indices = new int[Dim<D>.Count];
      for (int i = 0; i < Indices.Length; i++) Indices[i] = 0;
      var op = new ValueBrand<K, SCALAR, K, D1, SCALAR>.SwizzleOp<D>(Indices);
      return ToBrandD(op.Make(s.UnderlyingD));
    }
    public static BRAND Make(params SCALAR[] s) {
      var Es = new Expr<K>[Dim<D>.Count];
      for (int i = 0; i < Es.Length; i++) Es[i] = s[i].Provider;
      return ToBrandD(Composite<K, D>.Make(Es));
    }

    public SCALAR this[IntBl Index] {
      get { return ValueBrand<K, SCALAR, K, D1, SCALAR>.ToBrand(AccessExpr<K, D>.Make(UnderlyingD, Index)); }
      set { this[Index].Bind = value; } 
    }
    public static FlexBoolBl<D> operator ==(BRAND opB, BaseValueBrand<T, BRAND, K, D,SCALAR> opA) {
      return opB.Equal(opA);
    }
    public static FlexBoolBl<D> operator !=(BRAND opB, BaseValueBrand<T, BRAND, K, D, SCALAR> opA) {
      return opB.NotEqual(opA);
    }
    public new virtual FlexBoolBl<D> Equal(BRAND opB) {
      if (opB.Provider.Equals(this.Provider)) return FlexBoolBl<D>.Repeat(true);
      FlexBoolBl<D> result = EqualOp.Instance.Make(this, opB);
      result.ConvertByAll = true;
      return result;
    }
    public new virtual FlexBoolBl<D> NotEqual(BRAND opB) {
      if (opB.Provider.Equals(this.Provider)) return FlexBoolBl<D>.Repeat(false);
      FlexBoolBl<D> result = NotEqualOp.Instance.Make(this, opB);
      result.ConvertByAll = false; // if any is true then as bool is true.
      return result;
    }
    public override int GetHashCode() { return base.GetHashCode(); }
    public override bool Equals(object obj) { return base.Equals(obj); }



    // we have a dimension here, we can have dimension operators
    public abstract partial class UnaryOperatorS<S, CNT> : UnaryOperator<IVec<K, D>, S, CNT> where CNT : UnaryOperatorS<S, CNT> {}
    public abstract partial class UnaryOperatorD<S, CNT> : UnaryOperatorS<IVec<S, D>, CNT> where CNT : UnaryOperatorD<S, CNT> {
      public abstract Func<Expr<K>, Expr<S>> Uniform { get; }
      public sealed override Expr<IVec<S, D>> Expand(Expr<IVec<K, D>> argA) {
        var e = Expand0(argA);
        if (Dim<D>.Count > 1 && Uniform != null) {
          var Es = new Expr<S>[Dim<D>.Count];
          for (int i = 0; i < Es.Length; i++) {
            Es[i] = Uniform(AccessExpr<K, D>.Make(argA, i));
          }
          return Composite<S, D>.Make(Es);
        } else return e;
      }
      protected virtual Expr<IVec<S, D>> Expand0(Expr<IVec<K, D>> argA) {
        return base.Expand(argA);
      }
    }
    public abstract partial class BinaryOperatorS<S, CNT> : BinaryOperator<IVec<K, D>, IVec<K, D>, S, CNT> where CNT : BinaryOperatorS<S, CNT> {}
    public abstract partial class BinaryOperatorD<S, CNT> : BinaryOperatorS<IVec<S, D>, CNT> where CNT : BinaryOperatorD<S, CNT> {
      public abstract Func<Expr<K>, Expr<K>, Expr<S>> Uniform { get; }
      public sealed override Expr<IVec<S, D>> Expand(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB) {
        var e = Expand0(argA, argB);
        if (Dim<D>.Count > 1 && Uniform != null) {
          var Es = new Expr<S>[Dim<D>.Count];
          for (int i = 0; i < Es.Length; i++) {
            Es[i] = Uniform(AccessExpr<K, D>.Make(argA, i), AccessExpr<K, D>.Make(argB, i));
          }
          return Composite<S, D>.Make(Es);
        } else return e;
      }
      protected virtual Expr<IVec<S, D>> Expand0(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB) {
        return base.Expand(argA, argB);
      }
    }

    public abstract partial class TrinaryOperatorD<S, CNT> : TrinaryOperator<IVec<K, D>, IVec<S, D>, IVec<S, D>, IVec<S, D>, CNT> where CNT : TrinaryOperatorD<S, CNT> {
      public abstract Func<Expr<K>, Expr<S>, Expr<S>, Expr<S>> Uniform { get; }
      public sealed override Expr<IVec<S, D>> Expand(Expr<IVec<K, D>> argA, Expr<IVec<S, D>> argB, Expr<IVec<S, D>> argC) {
        var e = Expand0(argA, argB, argC);
        if (Dim<D>.Count > 1 && Uniform != null) {
          var Es = new Expr<S>[Dim<D>.Count];
          for (int i = 0; i < Es.Length; i++) {
            Es[i] = Uniform(AccessExpr<K, D>.Make(argA, i), AccessExpr<S, D>.Make(argB, i), AccessExpr<S, D>.Make(argC, i));
          }
          return Composite<S, D>.Make(Es);
        } else return e;
      }
      protected virtual Expr<IVec<S, D>> Expand0(Expr<IVec<K, D>> argA, Expr<IVec<S, D>> argB, Expr<IVec<S, D>> argC) {
        return base.Expand(argA, argB, argC);
      }
    }
    public abstract partial class CallUnaryOp<CNT> : UnaryOperatorD<K, CNT>, ICallOperator where CNT : CallUnaryOp<CNT> {}
    public abstract partial class CallBinaryOp<CNT> : BinaryOperatorD<K, CNT>, ICallOperator where CNT : CallBinaryOp<CNT> {}
    public abstract partial class CallTrinaryOp<CNT> : TrinaryOperatorD<K, CNT>, ICallOperator where CNT : CallTrinaryOp<CNT> {}
    public abstract class BinaryOp<CNT> : BinaryOperatorD<K, CNT>, ISyntaxOperator where CNT : BinaryOp<CNT> {
      public override bool IsCheap {
        get {
          return true;
        }
      }
    }
    public abstract class UnaryOp<CNT> : UnaryOperatorD<K, CNT>, ISyntaxOperator where CNT : UnaryOp<CNT> {
      public override bool IsCheap {
        get {
          return true;
        }
      }
    }


    public abstract new partial class EqualityOp<CNT> : BinaryOperatorD<bool, CNT>, ISyntaxOperator where CNT : EqualityOp<CNT> { }
    public new partial class EqualOp : EqualityOp<EqualOp> {
      public new static EqualOp Instance = new EqualOp();
      private EqualOp() { }
      public override string Name { get { return "=="; } }
      public override Func<Expr<K>, Expr<K>, Expr<bool>> Uniform {
        get { return ValueBrand<K, SCALAR, K, D1, SCALAR>.EqualOp.Instance.Bl(); }
      }

    }
    public new partial class NotEqualOp : EqualityOp<NotEqualOp> {
      public new static NotEqualOp Instance = new NotEqualOp();
      private NotEqualOp() { }
      public override string Name { get { return "!="; } }
      public override Func<Expr<K>, Expr<K>, Expr<bool>> Uniform {
        get { return ValueBrand<K, SCALAR, K, D1, SCALAR>.NotEqualOp.Instance.Bl(); }
      }
    }
    public partial class ConditionBOp : Ops.Operator<IVec<bool, D>, T, T, IVec<K,D>, ConditionBOp> {
      public new static readonly ConditionBOp Instance = new ConditionBOp();
      private ConditionBOp() { }
      public override SmartString Format(SmartString argA, SmartString argB, SmartString argC) {
        return "if (" + argA + ") " + argB + " else " + argC;
      }
      public override Expr<IVec<K,D>> Expand(Expr<IVec<bool, D>> argA, Expr<T> argB, Expr<T> argC) {
        FlexBoolBl<D> ArgA = (argA);
        BRAND ArgB = ToBrand(argB);
        BRAND ArgC = ToBrand(argC);
        Expr<K>[] Es = new Expr<K>[Dim<D>.Count];
        for (int i = 0; i < Dim<D>.Count; i++) {
          Es[i] = ArgA[i].Condition(ArgB[i], ArgC[i]);
        }
        return Composite<K, D>.Make(Es);
      }
    }
    public virtual BRAND ChooseB<BBRAND>(BoolBl<D, BBRAND> Test, BRAND Other) where BBRAND : BoolBl<D, BBRAND> {
      return ToBrandD(ConditionBOp.Instance.Make(Test, this, Other));
    }
  }
  public abstract partial class ValueBrand<T, BRAND, K, D, SCALAR> : BaseValueBrand<T, BRAND, K, D,SCALAR>
    where BRAND : ValueBrand<T, BRAND, K, D, SCALAR>
    where D : Dim<D> 
    where SCALAR : ValueBrand<K,SCALAR,K,D1,SCALAR> {
    public ValueBrand(Expr<T> Underlying) : base(Underlying) { }
    public ValueBrand(Expr<IVec<K, D>> Underlying) : base(Underlying) { }
    public ValueBrand(SCALAR[] Es) : base(Es) { }
    public ValueBrand() : base() { }
    public static FlexBoolBl<D> operator ==(ValueBrand<T, BRAND, K, D, SCALAR> opA, BRAND opB) {
      return opA.Equal(opB);
    }
    public static FlexBoolBl<D> operator !=(ValueBrand<T, BRAND, K, D, SCALAR> opA, BRAND opB) {
      return opA.NotEqual(opB);
    }
    public override int GetHashCode() { return base.GetHashCode(); }
    public override bool Equals(object obj) { return base.Equals(obj); }

  }
  /// <summary>
  /// Generic flex for when we don't know.
  /// </summary>
  public partial class FlexBl<K, D, SCALAR> : ValueBrand<IVec<K, D>, FlexBl<K, D, SCALAR>, K, D, SCALAR> 
    where D : Dim<D> 
    where SCALAR : ValueBrand<K,SCALAR,K,D1,SCALAR> {
    public FlexBl(Expr<IVec<K, D>> Underlying) : base(Underlying) { }
    public FlexBl(SCALAR[] Es) : base(Es) { }
    public FlexBl() : base() { }

    public static implicit operator FlexBl<K, D, SCALAR>(SCALAR a) { return FlexBl<K, D, SCALAR>.Repeat(a); }
  }
}
namespace Bling.Core {
  public abstract partial class BaseBoolBl<T, BRAND, D> : ValueBrand<T, BRAND, bool, D, BoolBl>
    where BRAND : BaseBoolBl<T, BRAND, D>
    where D : Dim<D> {
    public BaseBoolBl(Expr<T> Underlying) : base(Underlying) { }
    public BaseBoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public BaseBoolBl(BoolBl[] Es) : base(Es) { }
    public BaseBoolBl() : base() { }

    public new abstract partial class BinaryOp<CNT> : BinaryOperatorD<bool, CNT>, ISyntaxOperator where CNT : BinaryOp<CNT> { }
    public partial class AndOp : BinaryOp<AndOp> {
      public new static AndOp Instance = new AndOp();
      private AndOp() { }
      public override string Name { get { return "&&"; } }
      public override Func<Expr<bool>, Expr<bool>, Expr<bool>> Uniform {
        get { return BaseBoolBl<bool, BoolBl, D1>.AndOp.Instance.Bl(); }
      }
    }
    public partial class OrOp : BinaryOp<OrOp> {
      public new static OrOp Instance = new OrOp();
      private OrOp() { }
      public override string Name { get { return "||"; } }
      public override Func<Expr<bool>, Expr<bool>, Expr<bool>> Uniform {
        get { return BaseBoolBl<bool, BoolBl, D1>.OrOp.Instance.Bl(); }
      }
    }
    public partial class ExclusiveOrOp : BinaryOp<ExclusiveOrOp> {
      public new static ExclusiveOrOp Instance = new ExclusiveOrOp();
      private ExclusiveOrOp() { }
      public override string Name { get { return "^"; } }
      public override Func<Expr<bool>, Expr<bool>, Expr<bool>> Uniform {
        get { return BaseBoolBl<bool, BoolBl, D1>.ExclusiveOrOp.Instance.Bl(); }
      }
    }

    public partial class NotOp : UnaryOperatorD<bool, NotOp>, ISyntaxOperator {
      public new static NotOp Instance = new NotOp();
      private NotOp() { }
      public override string Name {
        get { return "!"; }
      }
      public override Func<Expr<bool>, Expr<bool>> Uniform {
        get { return BaseBoolBl<bool, BoolBl, D1>.NotOp.Instance.Bl(); }
      }
    }

    private static BRAND True0;
    public static BRAND True {
      get {
        if (((object)True0) == null) True0 = Repeat(true);
        return True0;
      }
    }
    private static BRAND False0;
    public static BRAND False {
      get {
        if (((object)False0) == null) False0 = Repeat(false);
        return False0;
      }
    }

    public virtual BRAND And(BRAND opB) {
      if (opB.Provider.Equals(False.Provider)) return False;
      if (this.Provider.Equals(False.Provider)) return False;
      if (opB.Provider.Equals(True.Provider)) return this;
      if (this.Provider.Equals(True.Provider)) return opB;
      return ToBrandD(AndOp.Instance.Make(this, opB));
    }
    public virtual BRAND Or(BRAND opB) {
      if (opB.Provider.Equals(True.Provider)) return True;
      if (this.Provider.Equals(True.Provider)) return True;
      if (opB.Provider.Equals(False.Provider)) return this;
      if (this.Provider.Equals(False.Provider)) return opB;
      return ToBrandD(OrOp.Instance.Make(this, opB));
    }

    public static BRAND operator &(BaseBoolBl<T, BRAND, D> opA, BRAND opB) {
      return opA.And(opB);
    }
    public static BRAND operator |(BaseBoolBl<T, BRAND, D> opA, BRAND opB) {
      return opA.Or(opB);
    }
    public static BRAND operator ^(BaseBoolBl<T, BRAND, D> opA, BRAND opB) {
      return ToBrandD(ExclusiveOrOp.Instance.Make(opA, opB));
    }
    public static BRAND operator !(BaseBoolBl<T, BRAND, D> opA) {
      if (opA.Provider.Equals(True.Provider)) return False;
      if (opA.Provider.Equals(False.Provider)) return True;

      return ToBrandD(NotOp.Instance.Make(opA));
    }
    public abstract partial class AnyAllOp<CNT> : UnaryOperatorS<bool,CNT>, INoLinqOperator where CNT : AnyAllOp<CNT> {
      public override SmartString Format(SmartString s) {
        return Name + "(" + s + ")";
      }
    }
    public class AnyOp : AnyAllOp<AnyOp> {
      public new static readonly AnyOp Instance = new AnyOp();
      private AnyOp() { }
      public override Expr<bool> Expand(Expr<IVec<bool, D>> argA) {
        BoolBl Ret = false;
        for (int i = 0; i < Dim<D>.Count; i++)
          Ret = Ret | AccessExpr<bool, D>.Make(argA, i);
        return Ret.Provider;
      }
      public override string Name {
        get { return "Any"; }
      }
    }
    public class AllOp : AnyAllOp<AllOp> {
      public new static readonly AllOp Instance = new AllOp();
      private AllOp() { }
      public override Expr<bool> Expand(Expr<IVec<bool, D>> argA) {
        BoolBl Ret = true;
        for (int i = 0; i < Dim<D>.Count; i++)
          Ret = Ret & AccessExpr<bool, D>.Make(argA, i);
        return Ret.Provider;
      }
      public override string Name { get { return "All"; } }
    }
    public virtual BoolBl Any {
      get {
        if (typeof(D) == typeof(D1)) return this[0];
        else return AnyOp.Instance.Make(this); 
      }
    }
    public virtual BoolBl All {
      get {
        if (typeof(D) == typeof(D1)) return this[0];
        return AllOp.Instance.Make(this);
      }
    }

  }
  public abstract partial class BoolBl<T, BRAND, D> : BaseBoolBl<T, BRAND, D>
    where BRAND : BoolBl<T, BRAND, D>
    where D : Dim<D> {
    public BoolBl(Expr<T> Underlying) : base(Underlying) { }
    public BoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public BoolBl(BoolBl[] Es) : base(Es) { }
    public BoolBl() : base() { }

    public static BRAND operator |(BRAND opA, BoolBl<T, BRAND, D> opB) {
      return opA.Or(opB);
    }
    public static BRAND operator &(BRAND opA, BoolBl<T, BRAND, D> opB) {
      return opA.And(opB);
    }
    public static BRAND operator ^(BRAND opA, BoolBl<T, BRAND, D> opB) {
      return ToBrandD(ExclusiveOrOp.Instance.Make(opA, opB));
    }
  }
  public abstract partial class BaseBoolBl : BoolBl<bool, BoolBl, D1> {
    public BaseBoolBl(Expr<bool> Underlying) : base(Underlying) { }
    public BaseBoolBl(Expr<IVec<bool, D1>> Underlying) : base(Underlying) { }
    public BaseBoolBl(BoolBl[] Es) : base(Es) { }
    public BaseBoolBl() : base() { }
    public BRAND Condition<BRAND>(IConditionTarget<BRAND> ArgA, BRAND ArgB) where BRAND : IConditionTarget<BRAND> {
      return ArgA.ChooseA(this, ArgB);
    }
  }
  public partial class BoolBl : BaseBoolBl,ICoreBrandT {
    public BoolBl(Expr<bool> Underlying) : base(Underlying) { }
    public BoolBl(Expr<IVec<bool, D1>> Underlying) : base(Underlying) { }
    public BoolBl(BoolBl[] Es) : base(Es) { }
    public BoolBl() : base() { }

    public static implicit operator BoolBl(Expr<bool> Underlying) { return new BoolBl(Underlying); }
    public static implicit operator BoolBl(bool Underlying) { return new Constant<bool>(Underlying); }
    public BRAND Condition<BRAND>(BRAND ArgA, IConditionTarget<BRAND> ArgB) where BRAND : IConditionTarget<BRAND> {
      return Condition((IConditionTarget<BRAND>)ArgA, (BRAND)ArgB);
    }
    public DoubleBl Condition(double dA, double dB) { return Condition(dA.Bl(), dB.Bl()); }
    public IntBl Condition(int dA, int dB) { return Condition(dA.Bl(), dB.Bl()); }
  }
  public abstract partial class BaseBoolBl<D, BRAND> : BoolBl<IVec<bool, D>, BRAND, D>
    where D : Dim<D>
    where BRAND : BoolBl<D, BRAND> {
    public BaseBoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public BaseBoolBl(BoolBl[] Es) : base(Es) { }
    public BaseBoolBl() : base() { }
    public VBRAND ConditionB<VBRAND, SCALAR>(IValueBrand<VBRAND, D, SCALAR> ArgA, VBRAND ArgB)
      where VBRAND : IValueBrand<VBRAND, D, SCALAR>
      where SCALAR : IValueBrand<SCALAR, D1, SCALAR> {
      return ArgA.ChooseB<BRAND>(this, ArgB);
    }
  }
  public abstract partial class BoolBl<D, BRAND> : BaseBoolBl<D,BRAND>
    where D : Dim<D>
    where BRAND : BoolBl<D, BRAND> {
    public BoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public BoolBl(BoolBl[] Es) : base(Es) { }
    public BoolBl() : base() { }

    public VBRAND ConditionB<VBRAND, SCALAR>(VBRAND ArgA, IValueBrand<VBRAND, D, SCALAR> ArgB)
      where VBRAND : IValueBrand<VBRAND, D, SCALAR>
      where SCALAR : IValueBrand<SCALAR, D1, SCALAR> {
      return this.ConditionB((IValueBrand<VBRAND, D, SCALAR>)ArgA, (VBRAND)ArgB);
    }
  }

  public abstract partial class BaseFlexBoolBl<D> : BoolBl<D, FlexBoolBl<D>> where D : Dim<D> {
    internal bool ConvertByAll = true;
    public BaseFlexBoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public BaseFlexBoolBl(BoolBl[] Es) : base(Es) { }
    public BaseFlexBoolBl() : base() { }
    public override int GetHashCode() {
      return base.GetHashCode() + ConvertByAll.GetHashCode();
    }
    public override bool Equals(object obj) {
      return base.Equals(obj) && ((FlexBoolBl<D>)obj).ConvertByAll == ConvertByAll;
    }

    public BoolBl Convert {
      get {
        return ConvertByAll ? All : Any;
      }
    }
    public BRAND Condition<BRAND>(IConditionTarget<BRAND> IfTrue, BRAND IfFalse) where BRAND : IConditionTarget<BRAND> {
      return Convert.Condition(IfTrue, IfFalse);
    }
    public DoubleBl Condition(double IfTrue, double IfFalse) {
      return Convert.Condition(IfTrue.Bl(), IfFalse.Bl());
    }
  }
  public partial class FlexBoolBl<D> : BaseFlexBoolBl<D> where D : Dim<D> {
    public FlexBoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public FlexBoolBl(BoolBl[] Es) : base(Es) { }
    public FlexBoolBl() : base() { }
    public static implicit operator FlexBoolBl<D>(Expr<IVec<bool, D>> Underlying) {
      return new FlexBoolBl<D>(Underlying);
    }
    public static implicit operator BoolBl(FlexBoolBl<D> Value) { return Value.Convert; }
    public static implicit operator FlexBoolBl<D>(BoolBl v) {
      var Es = new BoolBl[Dim<D>.Count];
      for (int i = 0; i < Dim<D>.Count; i++) Es[i] = v;
      return new FlexBoolBl<D>(Es);
    }
    public BRAND Condition<BRAND>(BRAND IfTrue, IConditionTarget<BRAND> IfFalse) where BRAND : IConditionTarget<BRAND> {
      return Convert.Condition(IfTrue, IfFalse);
    }
  }
  /// <summary>
  /// Unlike flex bool, cannot be converted implicitly in unit bool. Also, supports only 1 dimension. 
  /// </summary>
  public partial class BoolBl<D> : BoolBl<D, BoolBl<D>>, ICoreBrandT where D : Dim1D<D>, IMultiDim1D<D> {
    public BoolBl(Expr<IVec<bool, D>> Underlying) : base(Underlying) { }
    public BoolBl(BoolBl[] Es) : base(Es) { }
    public BoolBl() : base() { }
    public static implicit operator BoolBl<D>(FlexBoolBl<D> v) {
      return new BoolBl<D>(v.Provider);
    }
    public static implicit operator BoolBl<D>(BoolBl V) {
      var Es = new BoolBl[Dim<D>.Count];
      for (int i = 0; i < Es.Length; i++) Es[i] = V;
      return new BoolBl<D>(Es);
    }
  }
}
namespace Bling.Core {
  public interface INumeric<BRAND> : IValueBrand<BRAND>, IConditionTarget<BRAND> where BRAND : INumeric<BRAND> {
    BRAND Add(BRAND OpB);
    BRAND Subtract(BRAND OpB);
    BRAND Multiply(BRAND OpB);
    BRAND Divide(BRAND OpB);
    BRAND Mod(BRAND OpB);
    BRAND Negate { get; }
    /// <summary>
    ///     Returns the absolute value of a number.
    /// </summary>
    BRAND Abs { get; }
    /// <summary>
    /// Returns the smaller of two numbers.
    /// </summary>
    BRAND Min(BRAND other);
    /// <summary>
    /// Returns the larger of two numbers.
    /// </summary>
    BRAND Max(BRAND other);
    /// <summary>
    /// Clamps the specified value to the specified minimum and maximum range.    
    /// </summary>
    BRAND Clamp(BRAND min, BRAND max);
  }
  public interface INumeric<BRAND, SCALAR> : IValueBrand<BRAND, SCALAR>, INumeric<BRAND>
    where BRAND : INumeric<BRAND, SCALAR>
    where SCALAR : INumeric<SCALAR, SCALAR> {
    /// <summary>
    /// Minimum vector component.
    /// </summary>
    SCALAR Min();
    /// <summary>
    /// Maximum vector component.
    /// </summary>
    SCALAR Max();
  }

  public interface INumeric<BRAND, D, SCALAR> : IValueBrand<BRAND, D, SCALAR>, INumeric<BRAND,SCALAR>
    where BRAND : INumeric<BRAND, D, SCALAR>
    where SCALAR : INumeric<SCALAR, D1, SCALAR> where D : Dim<D> {}

  public abstract partial class BaseNumericBrand<T, BRAND, K, D, SCALAR> : ValueBrand<T, BRAND, K, D, SCALAR>, INumeric<BRAND,D,SCALAR>
    where BRAND : NumericBrand<T, BRAND, K, D, SCALAR>
    where D : Dim<D>
    where SCALAR : NumericBrand<K, SCALAR, K, D1, SCALAR> {
    public BaseNumericBrand(Expr<T> Underlying) : base(Underlying) {   }
    public BaseNumericBrand(Expr<IVec<K, D>> Underlying) : base(Underlying) { }
    public BaseNumericBrand(SCALAR[] Es) : base(Es) { }
    public BaseNumericBrand() : base() { }


    public partial class AddOp : BinaryOp<AddOp> {
      public new static AddOp Instance = new AddOp();
      private AddOp() { }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K,SCALAR,K,D1,SCALAR>.AddOp.Instance.Bl(); }
      }
      public override string Name { get { return "+"; } }
      public override Expr<IVec<K, D>> InverseA(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        // result = argA + argB
        // argA = result - argB
        return ToBrandD(result) - ToBrandD(argB);
      }
      public override Expr<IVec<K, D>> InverseB(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        return ToBrandD(result) - ToBrandD(argA);
      }
    }
    public partial class SubtractOp : BinaryOp<SubtractOp> {
      public new static SubtractOp Instance = new SubtractOp();
      private SubtractOp() { }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.SubtractOp.Instance.Bl(); }
      }
      public override string Name { get { return "-"; } }
      public override Expr<IVec<K, D>> InverseA(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        // result = argA - argB
        return ToBrandD(result) + ToBrandD(argB);
      }
      public override Expr<IVec<K, D>> InverseB(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        return ToBrandD(argA) - ToBrandD(result);
      }
    }
    public partial class MultiplyOp : BinaryOp<MultiplyOp> {
      public new static MultiplyOp Instance = new MultiplyOp();
      private MultiplyOp() { }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.MultiplyOp.Instance.Bl(); }
      }
      public override string Name { get { return "*"; } }
      public override Expr<IVec<K, D>> InverseA(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        // result = argA * argB
        return ToBrandD(result) / ToBrandD(argB);
      }
      public override Expr<IVec<K, D>> InverseB(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        return ToBrandD(result) / ToBrandD(argA);
      }
    }
    public partial class DivideOp : BinaryOp<DivideOp> {
      public new static DivideOp Instance = new DivideOp();
      private DivideOp() { }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.DivideOp.Instance.Bl(); }
      }
      public override string Name { get { return "/"; } }
      public override Expr<IVec<K, D>> InverseA(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        // result = argA / argB
        return ToBrandD(result) * ToBrandD(argB);
      }
      public override Expr<IVec<K, D>> InverseB(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> result) {
        // result / argA = 1 / argB
        // argA / result = argB
        return ToBrandD(argA) / ToBrandD(result);
      }
    }
    public partial class ModuloOp : BinaryOp<ModuloOp> {
      public new static ModuloOp Instance = new ModuloOp();
      private ModuloOp() { }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.ModuloOp.Instance.Bl(); }
      }
      public override string Name { get { return "%"; } }
    }
    public partial class NegateOp : UnaryOp<NegateOp> {
      public new static NegateOp Instance = new NegateOp();
      private NegateOp() { }
      public override string Name { get { return "-"; } }
      public override Func<Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.NegateOp.Instance.Bl(); }
      }
      public override Expr<IVec<K, D>> Inverse(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> result) {
        return - ToBrandD(result);
      }
      protected override Expr<IVec<K, D>> Expand0(Expr<IVec<K, D>> argA) {
        return Default - ToBrandD(argA);
      }
    }

    public partial class GreaterThanOp : EqualityOp<GreaterThanOp> {
      public new static GreaterThanOp Instance = new GreaterThanOp();
      private GreaterThanOp() { }
      public override string Name { get { return ">"; } }
      public override Func<Expr<K>, Expr<K>, Expr<bool>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.GreaterThanOp.Instance.Bl(); }
      }
    }
    public partial class LessThanOp : EqualityOp<LessThanOp> {
      public new static LessThanOp Instance = new LessThanOp();
      private LessThanOp() { }
      public override string Name { get { return "<"; } }
      public override Func<Expr<K>, Expr<K>, Expr<bool>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.LessThanOp.Instance.Bl(); }
      }
    }
    public partial class GreaterThanOrEqualOp : EqualityOp<GreaterThanOrEqualOp> {
      public new static GreaterThanOrEqualOp Instance = new GreaterThanOrEqualOp();
      private GreaterThanOrEqualOp() { }
      public override string Name { get { return ">="; } }
      public override Func<Expr<K>, Expr<K>, Expr<bool>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.GreaterThanOrEqualOp.Instance.Bl(); }
      }
    }
    public partial class LessThanOrEqualOp : EqualityOp<LessThanOrEqualOp> {
      public new static LessThanOrEqualOp Instance = new LessThanOrEqualOp();
      private LessThanOrEqualOp() { }
      public override string Name { get { return "<="; } }
      public override Func<Expr<K>, Expr<K>, Expr<bool>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.LessThanOrEqualOp.Instance.Bl(); }
      }
    }
    public partial class AbsOp : CallUnaryOp<AbsOp>, IMathLinqOperator {
      public new static AbsOp Instance = new AbsOp();
      private AbsOp() { }
      public override string Name { get { return "Abs"; } }
      public override Func<Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.AbsOp.Instance.Bl(); }
      }
      protected override Expr<IVec<K, D>> Expand0(Expr<IVec<K, D>> argA) {
        return (ToBrandD(argA) < Default).ConditionB(ToBrandD(argA).Negate, ToBrandD(argA));
      }
    }
    public partial class MinOp : CallBinaryOp<MinOp>, IMathLinqOperator {
      public new static MinOp Instance = new MinOp();
      private MinOp() { }
      public override string Name { get { return "Min"; } }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.MinOp.Instance.Bl(); }
      }
      protected override Expr<IVec<K, D>> Expand0(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB) {
        return (ToBrandD(argA) < ToBrandD(argB)).ConditionB(ToBrandD(argA), ToBrandD(argB));
      }
    }
    public partial class MaxOp : CallBinaryOp<MaxOp>, IMathLinqOperator {
      public new static MaxOp Instance = new MaxOp();
      private MaxOp() { }
      public override string Name { get { return "Max"; } }
      public override Func<Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.MaxOp.Instance.Bl(); }
      }
      protected override Expr<IVec<K, D>> Expand0(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB) {
        return (ToBrandD(argA) > ToBrandD(argB)).ConditionB(ToBrandD(argA), ToBrandD(argB));
      }
    }
    public partial class ClampOp : CallTrinaryOp<ClampOp>, INoLinqOperator {
      public new static ClampOp Instance = new ClampOp();
      private ClampOp() { }
      public override string Name { get { return "Clamp"; } }
      public override Func<Expr<K>, Expr<K>, Expr<K>, Expr<K>> Uniform {
        get { return BaseNumericBrand<K, SCALAR, K, D1, SCALAR>.ClampOp.Instance.Bl(); }
      }
      protected override Expr<IVec<K, D>> Expand0(Expr<IVec<K, D>> argA, Expr<IVec<K, D>> argB, Expr<IVec<K, D>> argC) {
        return ToBrandD(argA).Max(ToBrandD(argB)).Min(ToBrandD(argC));
      }
    }

    public virtual BRAND Add(BRAND OpB) { return ToBrandD(AddOp.Instance.Make(this, OpB)); }
    public virtual BRAND Subtract(BRAND OpB) { return ToBrandD(SubtractOp.Instance.Make(this, OpB)); }
    public virtual BRAND Multiply(BRAND OpB) { 
      return ToBrandD(MultiplyOp.Instance.Make(this, OpB)); 
    }
    public virtual BRAND Divide(BRAND OpB) { return ToBrandD(DivideOp.Instance.Make(this, OpB)); }
    public virtual BRAND Mod(BRAND OpB) { return ToBrandD(ModuloOp.Instance.Make(this, OpB)); }
    public virtual BRAND Negate { get { return ToBrandD(NegateOp.Instance.Make(this)); } }
    /// <summary>
    ///     Returns the absolute value of a number.
    /// </summary>
    public virtual BRAND Abs { get { return ToBrandD(AbsOp.Instance.Make(this)); } }
    /// <summary>
    /// Returns the smaller of two numbers.
    /// </summary>
    public virtual BRAND Min(BRAND other) { return ToBrandD(MinOp.Instance.Make(this, other)); }
    /// <summary>
    /// Returns the larger of two numbers.
    /// </summary>
    public virtual BRAND Max(BRAND other) { return ToBrandD(MaxOp.Instance.Make(this, other)); }
    /// <summary>
    /// Clamps the specified value to the specified minimum and maximum range.    
    /// </summary>
    public virtual BRAND Clamp(BRAND min, BRAND max) { return ToBrandD(ClampOp.Instance.Make(this, min, max)); }
    /// <summary>
    /// Clamps the specified value to the specified maximum range from a default minimum range (0).    
    /// </summary>
    public BRAND Clamp(BRAND max) { return Clamp(Default, max); }

    // operator syntax definitions.
    public static BRAND operator +(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return OpA.Add(OpB);
    }
    public static BRAND operator -(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return OpA.Subtract(OpB);
    }
    public static BRAND operator *(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return OpA.Multiply(OpB);
    }
    public static BRAND operator /(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return OpA.Divide(OpB);
    }
    public static BRAND operator %(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return OpA.Mod(OpB);
    }
    public static FlexBoolBl<D> operator >(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return GreaterThanOp.Instance.Make(OpA, OpB);
    }
    public static FlexBoolBl<D> operator <(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return LessThanOp.Instance.Make(OpA, OpB);
    }
    public static FlexBoolBl<D> operator >=(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return GreaterThanOrEqualOp.Instance.Make(OpA, OpB);
    }
    public static FlexBoolBl<D> operator <=(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA, BRAND OpB) {
      return LessThanOrEqualOp.Instance.Make(OpA, OpB);
    }

    public static BRAND operator -(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA) {
      return ToBrandD(OpA.Negate);
    }
    public static BRAND operator +(BaseNumericBrand<T, BRAND, K, D, SCALAR> OpA) {
      return (BRAND) OpA;
    }
    /// <summary>
    /// Mimimum vector component
    /// </summary>
    public SCALAR Min() {
      var min = this[0];
      for (int i = 1; i < Dim<D>.Count; i++)
        min = min.Min(this[i]);
      return min;
    }
    /// <summary>
    /// Maxiumum vector component
    /// </summary>
    public SCALAR Max() {
      var max = this[0];
      for (int i = 1; i < Dim<D>.Count; i++)
        max = max.Max(this[i]);
      return max;
    }
    static BaseNumericBrand() {
      true.Assert();
    }
  }
  public abstract partial class NumericBrand<T, BRAND, K, D, SCALAR> : BaseNumericBrand<T, BRAND, K, D, SCALAR>
    where BRAND : NumericBrand<T, BRAND, K, D, SCALAR>
    where D : Dim<D>
    where SCALAR : NumericBrand<K, SCALAR, K, D1, SCALAR> {
    public NumericBrand(Expr<T> Underlying) : base(Underlying) { }
    public NumericBrand(Expr<IVec<K, D>> Underlying) : base(Underlying) { }
    public NumericBrand(params SCALAR[] Es) : base(Es) { }
    public NumericBrand() : base() { }

    public static BRAND operator +(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return OpA.Add(OpB);
    }
    public static BRAND operator +(K OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return Repeat(OpA).Add(OpB);
    }
    public static BRAND operator +(NumericBrand<T, BRAND, K, D, SCALAR> OpA, K OpB) {
      return (OpA).Add(Repeat(OpB));
    }
    public static BRAND operator -(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return OpA.Subtract(OpB);
    }
    public static BRAND operator -(K OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return Repeat(OpA).Subtract(OpB);
    }
    /// <summary>
    /// Subtract two numbers.
    /// </summary>
    public static BRAND operator -(NumericBrand<T, BRAND, K, D, SCALAR> OpA, K OpB) {
      return (OpA).Subtract(Repeat(OpB));
    }
    public static BRAND operator *(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return OpA.Multiply(OpB);
    }
    public static BRAND operator *(K OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return Repeat(OpA).Multiply(OpB);
    }
    public static BRAND operator *(NumericBrand<T, BRAND, K, D, SCALAR> OpA, K OpB) {
      return (OpA).Multiply(Repeat(OpB));
    }
    public static BRAND operator /(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return OpA.Divide(OpB);
    }
    public static BRAND operator /(K OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return Repeat(OpA).Divide(OpB);
    }
    /// <summary>
    /// Divide two numbers.
    /// </summary>
    public static BRAND operator /(NumericBrand<T, BRAND, K, D, SCALAR> OpA, K OpB) {
      return (OpA).Divide(Repeat(OpB));
    }
    public static BRAND operator %(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return OpA.Mod(OpB);
    }
    public static FlexBoolBl<D> operator >(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return GreaterThanOp.Instance.Make(OpA, OpB);
    }
    public static FlexBoolBl<D> operator >(K OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return GreaterThanOp.Instance.Make(Repeat(OpA), OpB);
    }
    public static FlexBoolBl<D> operator >(NumericBrand<T, BRAND, K, D, SCALAR> OpA, K OpB) {
      return GreaterThanOp.Instance.Make(OpA, Repeat(OpB));
    }
    public static FlexBoolBl<D> operator <(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return LessThanOp.Instance.Make(OpA, OpB);
    }
    public static FlexBoolBl<D> operator <(K OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return LessThanOp.Instance.Make(Repeat(OpA), OpB);
    }
    public static FlexBoolBl<D> operator <(NumericBrand<T, BRAND, K, D, SCALAR> OpA, K OpB) {
      return LessThanOp.Instance.Make((OpA), Repeat(OpB));
    }
    public static FlexBoolBl<D> operator >=(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return GreaterThanOrEqualOp.Instance.Make(OpA, OpB);
    }
    public static FlexBoolBl<D> operator <=(BRAND OpA, NumericBrand<T, BRAND, K, D, SCALAR> OpB) {
      return LessThanOrEqualOp.Instance.Make(OpA, OpB);
    }
  }
}
namespace Bling.Core {
  public abstract partial class IntBl<T, BRAND, D> : NumericBrand<T, BRAND, int, D, IntBl>
    where BRAND : IntBl<T, BRAND, D>
    where D : Dim<D> {
    public IntBl(Expr<T> Underlying) : base(Underlying) { }
    public IntBl(Expr<IVec<int, D>> Underlying) : base(Underlying) { }
    public IntBl(IntBl[] Es) : base(Es) { }
    public IntBl() : base() { }
  }

  public partial class IntBl : IntBl<int, IntBl, D1>, ICoreBrandT {
    public IntBl(Expr<int> Underlying) : base(Underlying) { }
    public IntBl(Expr<IVec<int, D1>> Underlying) : base(Underlying) { }
    public IntBl(IntBl[] Es) : base(Es) { }
    public IntBl() : base() { }
    public static implicit operator IntBl(IntBl<D1> v) {
      return new IntBl(v.Provider);
    }
    public static implicit operator IntBl<D1>(IntBl v) {
      return new IntBl<D1>(new IntBl[] { v });
    }
    public static implicit operator IntBl(Expr<int> Underlying) { return new IntBl(Underlying); }
    public static implicit operator IntBl(int Underlying) { return new Constant<int>(Underlying); }

    public static implicit operator DoubleBl(IntBl v) {
      return v.Coerce<double, DoubleBl>();
    }
    public static explicit operator IntBl(DoubleBl v) {
      return v.Coerce<int, IntBl>();
    }

  }
  public partial class IntBl<D, BRAND> : IntBl<IVec<int, D>, BRAND, D>
    where D : Dim<D>
    where BRAND : IntBl<D, BRAND> {
    public IntBl(Expr<IVec<int, D>> Underlying) : base(Underlying) { }
    public IntBl(IntBl[] Es) : base(Es) { }
    public IntBl() : base() { }
  }
  public partial class FlexIntBl<D> : IntBl<D, FlexIntBl<D>> where D : Dim<D> {
    public FlexIntBl(Expr<IVec<int, D>> Underlying) : base(Underlying) { }
    public FlexIntBl(IntBl[] Es) : base(Es) { }
    public FlexIntBl() : base() { }
    public static implicit operator FlexIntBl<D>(Expr<IVec<int, D>> Underlying) { return new FlexIntBl<D>(Underlying); }

    public static implicit operator FlexIntBl<D>(IntBl I) { return Repeat(I); }
    public static implicit operator FlexIntBl<D>(int I) { return I.Bl(); }
    public static implicit operator FlexDoubleBl<D>(FlexIntBl<D> I) {
      var Ds = new DoubleBl[Dim<D>.Count];
      for (int i = 0; i < Ds.Length; i++) Ds[i] = I[i];
      return new FlexDoubleBl<D>(Ds);
    }
    public static explicit operator FlexIntBl<D>(FlexDoubleBl<D> I) {
      var Ds = new IntBl[Dim<D>.Count];
      for (int i = 0; i < Ds.Length; i++) Ds[i] = (IntBl) I[i];
      return new FlexIntBl<D>(Ds);
    }

    // public static implicit operator FlexIntBl<D>(IVec<int, D> Underlying) { return new Constant<IVec<int, D>>(Underlying); }
  }
  public partial class IntBl<D> : IntBl<D, IntBl<D>>, ICoreBrandT where D : Dim1D<D> {
    public IntBl(Expr<IVec<int, D>> Underlying) : base(Underlying) { }
    public IntBl(params IntBl[] Es) : base(Es) { }
    public IntBl() : base() { }
    public static implicit operator IntBl<D>(FlexIntBl<D> V) { return new IntBl<D>(V.Provider); }
    public static implicit operator FlexIntBl<D>(IntBl<D> V) { return new FlexIntBl<D>(V.Provider); }
    public static implicit operator IntBl<D>(Expr<IVec<int, D>> Underlying) { return new IntBl<D>(Underlying); }

    public static implicit operator IntBl<D>(IntBl V) {
      var Es = new IntBl[Dim<D>.Count];
      for (int i = 0; i < Es.Length; i++) Es[i] = V;
      return new IntBl<D>(Es);
    }
  }
}
namespace Bling.Core {
  //using Bling.Matrices;
  public partial interface IDouble {
  }
  public interface ICanInterpolate {
    Func<object, object, DoubleBl, object> BaseCoreInterpolate { get; }
  }
  public interface ICanInterpolate<BRAND> : ICanInterpolate {
    Func<BRAND, BRAND, DoubleBl, BRAND> CoreInterpolate { get; }

    //BRAND CoreInterpolate(BRAND To, DoubleBl t);
  }

  public interface IDouble<BRAND> : INumeric<BRAND>, IDouble, ICanInterpolate<BRAND> where BRAND : IDouble<BRAND> {
    /// <summary>
    /// Clamp components between 0 and 1.
    /// </summary>
    BRAND Saturate { get; }
    /// <summary>
    ///     Returns the largest number less than or equal to this number.
    /// </summary>
    BRAND Floor { get; }
    /// <summary>
    ///     Returns the smallest number less than or equal to this number.
    /// </summary>
    BRAND Ceiling { get; }
    /// <summary>
    ///     Rounds a decimal value to the nearest integer. Returns
    ///     the number nearest parameter d. If the fractional component of d is halfway
    ///     between two numbers, one of which is even and the other odd, then the even
    ///     number is returned.
    /// </summary>
    BRAND Round { get; }
    BRAND Exp { get; }
    BRAND Log { get; }
    BRAND Exp2 { get; }
    BRAND Log2 { get; }
    BRAND Exp10 { get; }
    BRAND Log10 { get; }
    BRAND Pow(BRAND Power);
    BRAND LogN(BRAND Base);
    BRAND Recip { get; }
    BRAND Square { get; }
    BRAND Sqrt { get; }
    BRAND Rsqrt { get; }
    BRAND Ddx { get; }
    BRAND Ddy { get; }
    BRAND Fwidth { get; }
    BRAND Frac { get; }
    BRAND Ldexp(BRAND other);

    BRAND RawNormalize { get; }
    BRAND Normalize { get; }

  }
  public partial interface IDouble2<BRAND> : IDouble<BRAND> where BRAND : IDouble2<BRAND> {
    BoolBl IsInfinity { get; }
    BoolBl IsFinite { get; }
    BoolBl IsNaN { get; }
    BoolBl IsPositiveInfinity { get; }
    BoolBl IsNegativeInfinity { get; }
    DoubleBl Dot(BRAND Other);
    DoubleBl LengthSquared { get; }
    DoubleBl Length { get; }
    DoubleBl Distance(BRAND other);
  }


  public partial interface IDouble<BRAND, D> : IDouble<BRAND>
    where BRAND : IDouble<BRAND, D>
    where D : Dim<D> {
    Expr<IVec<double, D>> UnderlyingD { get; }
    Core.StringBl ToStringBl(DoubleBl e);
    FlexIntBl<D> Sign { get; }
    FlexDoubleBl<D> SafeSign { get; }
    
  }
  public static class MakeIDouble<BRAND, D>
    where BRAND : IDouble<BRAND, D>
    where D : Dim<D> {
    public static BRAND ToBrandD(Expr<IVec<double, D>> Underlying) {
      return (BRAND) typeof(BRAND).GetConstructor(new Type[] { typeof(Expr<IVec<double, D>>) }).Invoke(new object[] { Underlying });
    }
  }
  /// <summary>
  /// Base class of all double-like numeric types.
  /// </summary>
  public abstract partial class DoubleBl<T, BRAND, D> : NumericBrand<T, BRAND, double, D, DoubleBl>, IHasX<double,DoubleBl>, IDouble<BRAND,D>, IDouble2<BRAND>
    where BRAND : DoubleBl<T, BRAND, D>
    where D : Dim<D> {
    public DoubleBl(Expr<T> Underlying) : base(Underlying) { }
    public DoubleBl(Expr<IVec<double, D>> Underlying) : base(Underlying) { }
    public DoubleBl(params DoubleBl[] Es) : base(Es) { }
    public DoubleBl() : base() { }

    public static BRAND Random { get { return RandomFrom(new Random()); } }
    public static BRAND RandomFrom(Random r) {
      var Es = new DoubleBl[Dim<D>.Count];
      for (int i = 0; i < Es.Length; i++) {
        Es[i] = DoubleBl.State(r.NextDouble);
      }
      var flex = new FlexDoubleBl<D>(Es);
      return ToBrandD(flex.UnderlyingD);
    }      

    public Func<object, object, DoubleBl, object> BaseCoreInterpolate {
      get { return (x, y, t) => CoreInterpolate((BRAND)x, (BRAND)y, t); }
    }
    public virtual Func<BRAND, BRAND, DoubleBl, BRAND> CoreInterpolate {
      get {
        return (x0, y0, t) => ToBrandD(LerpOp.Instance.Make(x0,y0,t));
      }
    }

    public static BRAND NaN { get { return Repeat(double.NaN); } }

    public virtual Core.StringBl ToStringBl(DoubleBl e) {
      var p = this.Multiply(Repeat(e)).Round.Divide(Repeat(e));
      return p.ToStringBl();
    }
    public partial class LerpOp : TrinaryOperator<IVec<double,D>, IVec<double,D>, double, IVec<double,D>, LerpOp>, INoLinqOperator, ICallOperator {
      public new static LerpOp Instance = new LerpOp();
      private LerpOp() { }
      public override string Name { get { return "Lerp"; } }
      public override Expr<IVec<double, D>> Expand(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> argB, Expr<double> argC) {
        var x = ToBrandD(argA);
        var y = ToBrandD(argB);
        DoubleBl s = (argC);
        return (x + Repeat(s) * (y - x)).UnderlyingD;
      }
    }



    public partial class SaturateOp : CallUnaryOp<SaturateOp>, INoLinqOperator {
      public new static SaturateOp Instance = new SaturateOp();
      private SaturateOp() { }

      public override string Name { get { return "Saturate"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.SaturateOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) {
        BRAND ArgA = ToBrandD(argA);
        return ArgA.Clamp(Repeat(0d), Repeat(1d));
      }
    }
    public partial class FloorOp : CallUnaryOp<FloorOp>, IMathLinqOperator {
      public new static FloorOp Instance = new FloorOp();
      private FloorOp() { }
      public override string Name { get { return "Floor"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.FloorOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) {
        BRAND ArgA = ToBrandD(argA);
        return ArgA - (ArgA % Repeat(1d));
      }
    }
    public partial class CeilingOp : CallUnaryOp<CeilingOp>, IMathLinqOperator, ICustomShaderCallOperator {
      public new static CeilingOp Instance = new CeilingOp();
      private CeilingOp() { }
      public override string Name { get { return "Ceiling"; } }
      public string ShaderName { get { return "ceil"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.CeilingOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) {
        BRAND ArgA = ToBrandD(argA);
        return ArgA + (Repeat(1d) - (ArgA % Repeat(1d)));
      }
    }
    public partial class RoundOp : CallUnaryOp<RoundOp>, IMathLinqOperator {
      public new static RoundOp Instance = new RoundOp();
      private RoundOp() { }
      public override string Name { get { return "Round"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.RoundOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) {
        BRAND ArgA = ToBrandD(argA);
        var mod = ArgA % Repeat(1d);
        return (mod.Abs < Repeat(.5d)).ConditionB(ArgA - mod, ArgA + (Repeat(1d) - mod));
      }
    }
    public partial class SignOp : UnaryOperatorD<int, SignOp>, INoLinqOperator {
      public new static SignOp Instance = new SignOp();
      private SignOp() { }
      public override string Name { get { return "Sign"; } }
      public override Func<Expr<double>, Expr<int>> Uniform {
        get { return DoubleBl.SignOp.Instance.Bl(); }
      }
      protected override Expr<IVec<int, D>> Expand0(Expr<IVec<double, D>> argA) {
        FlexIntBl<D> Positive = FlexIntBl<D>.Repeat(+1);
        FlexIntBl<D> Negative = FlexIntBl<D>.Repeat(-1);

        return (ToBrandD(argA) >= Repeat(0)).ConditionB(Positive, Negative);
      }
    }
    public partial class ExpOp : CallUnaryOp<ExpOp>, IMathLinqOperator {
      public new static ExpOp Instance = new ExpOp();
      private ExpOp() { }
      public override string Name { get { return "Exp"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.ExpOp.Instance.Bl(); }
      }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) {
        return ToBrandD(result).Log;
      }
    }
    public partial class LogOp : CallUnaryOp<LogOp>, IMathLinqOperator {
      public new static LogOp Instance = new LogOp();
      private LogOp() { }
      public override string Name { get { return "Log"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.LogOp.Instance.Bl(); }
      }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) {
        return ToBrandD(result).Exp;
      }
    }
    public partial class Exp2Op : CallUnaryOp<Exp2Op>, INoLinqOperator {
      public new static readonly Exp2Op Instance = new Exp2Op();
      private Exp2Op() { }
      public override string Name { get { return "Exp2"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.Exp2Op.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return Repeat(2d).Pow(ToBrandD(argA)); }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Log2; }
    }
    public partial class Log2Op : CallUnaryOp<Log2Op>, INoLinqOperator {
      public new static readonly Log2Op Instance = new Log2Op();
      private Log2Op() { }
      public override string Name { get { return "Log2"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.Log2Op.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return ToBrandD(argA).LogN(Repeat(2d)); }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Exp2; }
    }
    public partial class Exp10Op : CallUnaryOp<Exp10Op>, IMathLinqOperator, INoShaderOperator {
      public new static readonly Exp10Op Instance = new Exp10Op();
      private Exp10Op() { }
      public override string Name { get { return "Exp10"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.Exp10Op.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return Repeat(10d).Pow(ToBrandD(argA)); }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Log10; }
    }
    public partial class Log10Op : CallUnaryOp<Log10Op>, IMathLinqOperator {
      public new static readonly Log10Op Instance = new Log10Op();
      private Log10Op() { }
      public override string Name { get { return "Log10"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.Log10Op.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return ToBrandD(argA).LogN(Repeat(10d)); }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Exp10; }
    }

    public partial class PowOp : CallBinaryOp<PowOp>, IMathLinqOperator {
      public new static readonly PowOp Instance = new PowOp();
      private PowOp() { }
      public override string Name { get { return "Pow"; } }
      public override Func<Expr<double>, Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.PowOp.Instance.Bl(); }
      }
      public override Expr<IVec<double, D>> InverseB(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> argB, Expr<IVec<double, D>> result) {
        var Base = ToBrandD(argA);
        var Power = ToBrandD(argB);
        var Raised = ToBrandD(result);
        // Raised = Pow(Base, Power);
        return Raised.LogN(Base);
      }
    }
    public partial class LogNOp : CallBinaryOp<LogNOp>, ICustomLinqCallOperator, INoShaderOperator {
      public new static readonly LogNOp Instance = new LogNOp();
      private LogNOp() { }
      public Type From { get { return typeof(Math); } }
      public override string Name { get { return "Log"; } }
      public override Func<Expr<double>, Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.LogNOp.Instance.Bl(); }
      }
      public override Expr<IVec<double, D>> InverseB(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> argB, Expr<IVec<double, D>> result) {
        var Power = ToBrandD(result);
        var Raised = ToBrandD(argA);
        var Base = ToBrandD(argB);
        // Power = Log(Raised, Base)
        return Base.Pow(Power);
      }
    }

    public partial class RecipOp : CallUnaryOp<RecipOp>, INoLinqOperator, INoShaderOperator {
      public new static readonly RecipOp Instance = new RecipOp();
      private RecipOp() { }
      public override string Name { get { return "Recip"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.RecipOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return Repeat(1d) / ToBrandD(argA); }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Recip; }
    }
    public partial class SquareOp : CallUnaryOp<SquareOp>, INoLinqOperator, INoShaderOperator {
      public new static readonly SquareOp Instance = new SquareOp();
      private SquareOp() { }
      public override string Name { get { return "Square"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return true ? null : DoubleBl.SquareOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return ToBrandD(argA) * ToBrandD(argA); }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Sqrt; }
    }
    public partial class SqrtOp : CallUnaryOp<SqrtOp>, IMathLinqOperator {
      public new static readonly SqrtOp Instance = new SqrtOp();
      private SqrtOp() { }
      public override string Name { get { return "Sqrt"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.SqrtOp.Instance.Bl(); }
      }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Square; }
    }
    public partial class RsqrtOp : CallUnaryOp<RsqrtOp>, INoLinqOperator {
      public new static readonly RsqrtOp Instance = new RsqrtOp();
      private RsqrtOp() { }
      public override string Name { get { return "Rsqrt"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.RsqrtOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return ToBrandD(argA).Recip.Sqrt; }
      public override Expr<IVec<double, D>> Inverse(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> result) { return ToBrandD(result).Square.Recip; }
    }
    public partial class FracOp : CallUnaryOp<FracOp>, INoLinqOperator {
      public new static readonly FracOp Instance = new FracOp();
      private FracOp() { }
      public override string Name { get { return "Frac"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.FracOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { return (ToBrandD(argA) % Repeat(1d)).Abs; }
    }
    public partial class LdexpOp : CallBinaryOp<LdexpOp>, INoLinqOperator {
      public new static readonly LdexpOp Instance = new LdexpOp();
      private LdexpOp() { }
      public override string Name { get { return "Ldexp"; } }
      public override Func<Expr<double>, Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.LdexpOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> argB) {
        var x = ToBrandD(argA);
        var exp = ToBrandD(argB);
        return x * exp.Exp2;
      }
    }
    public partial class DdxOp : CallUnaryOp<DdxOp>, INoLinqOperator {
      public new static readonly DdxOp Instance = new DdxOp();
      private DdxOp() { }
      public override string Name { get { return "Ddx"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.DdxOp.Instance.Bl(); }
      }
    }
    public partial class DdyOp : CallUnaryOp<DdyOp>, INoLinqOperator {
      public new static readonly DdyOp Instance = new DdyOp();
      private DdyOp() { }
      public override string Name { get { return "Ddy"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.DdyOp.Instance.Bl(); }
      }
    }
    public partial class FwidthOp : CallUnaryOp<FwidthOp>, INoLinqOperator {
      public new static readonly FwidthOp Instance = new FwidthOp();
      private FwidthOp() { }
      public override string Name { get { return "Fwidth"; } }
      public override Func<Expr<double>, Expr<double>> Uniform {
        get { return DoubleBl.FwidthOp.Instance.Bl(); }
      }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) {
        var ArgA = ToBrandD(argA);
        return ArgA.Ddx.Abs + ArgA.Ddy.Abs;
      }
    }
    public partial class DotOp : BinaryOperatorS<double, DotOp>, INoLinqOperator {
      public override string Name {
        get { return "Dot"; }
      }
      public new static readonly DotOp Instance = new DotOp();
      private DotOp() { }
      public override SmartString Format(SmartString argA, SmartString argB) {
        return argA + ".." + argB;
      }
      public override Expr<double> Expand(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> argB) {
        var ArgA = ToBrandD(argA);
        var ArgB = ToBrandD(argB);
        DoubleBl Result = 0;
        for (int i = 0; i < Dim<D>.Count; i++)
          Result += ArgA[i] * ArgB[i];
        return Result.Provider;
      }
    }

    public partial class LengthSquaredOp : UnaryOperatorS<double, LengthSquaredOp>, INoLinqOperator, INoShaderOperator {
      public new static readonly LengthSquaredOp Instance = new LengthSquaredOp();
      private LengthSquaredOp() { }
      public override string Name { get { return "LengthSquared"; } }
      public override Expr<double> Expand(Expr<IVec<double, D>> argA) { return ToBrandD(argA).Dot(ToBrandD(argA)); }
    }
    public partial class LengthOp : UnaryOperatorS<double, LengthOp>, INoLinqOperator {
      public new static readonly LengthOp Instance = new LengthOp();
      private LengthOp() { }
      public override string Name { get { return "Length"; } }
      public override Expr<double> Expand(Expr<IVec<double, D>> argA) {
        return ToBrandD(argA).LengthSquared.Sqrt;
      }
    }
    public partial class NormalizeOp : CallUnaryOp<NormalizeOp>, INoLinqOperator {
      public new static readonly NormalizeOp Instance = new NormalizeOp();
      private NormalizeOp() { }
      public override string Name { get { return "Normalize"; } }
      public override Func<Expr<double>, Expr<double>> Uniform { get { return null; } }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) { 
        return ToBrandD(argA) / 
          Repeat(ToBrandD(argA).Length); 
      }
    }
    public partial class SafeNormalizeOp : CallUnaryOp<SafeNormalizeOp>, INoLinqOperator, INoShaderOperator {
      public new static readonly SafeNormalizeOp Instance = new SafeNormalizeOp();
      private SafeNormalizeOp() { }
      public override string Name { get { return "SafeNormalize"; } }
      public override Func<Expr<double>, Expr<double>> Uniform { get { return null; } }
      protected override Expr<IVec<double, D>> Expand0(Expr<IVec<double, D>> argA) {
        var ArgA = ToBrandD(argA);
        var length = ArgA.LengthSquared;
        var ret = ArgA.RawNormalize;
        return (length == 0d).Condition(Unit, ret);
      }
      public override Func<SmartString, SmartString> Shader<EVAL>(Bling.Shaders.BaseShaderEval<EVAL> txt, Bling.Ops.Operation<IVec<double, D>, IVec<double, D>> op) {
        return s => "normalize(" + s + ")";
      }
    }

    public partial class DistanceOp : BinaryOperatorS<double, DistanceOp>, INoLinqOperator {
      public new static readonly DistanceOp Instance = new DistanceOp();
      private DistanceOp() { }
      public override string Name { get { return "Distance"; } }
      public override Expr<double> Expand(Expr<IVec<double, D>> argA, Expr<IVec<double, D>> argB) {
        return (ToBrandD(argB) - ToBrandD(argA)).Length;
      }
    }
    public abstract partial class IsOp<CNT> : UnaryOperatorS<bool, CNT>, ITypeLinqOperator where CNT : IsOp<CNT> {
      public abstract Func<Expr<double>, Expr<bool>> Uniform { get; }
      public override Expr<bool> Expand(Expr<IVec<double, D>> argA) {
        if (Dim<D>.Count == 1) return base.Expand(argA);
        BoolBl result = false;
        var ArgA = ToBrandD(argA);
        for (int i = 0; i < Dim<D>.Count; i++) {
          result = result | Uniform(ArgA[i]).Bl();
        }
        return result;
      }
    }
    public class IsNaNOp : IsOp<IsNaNOp> {
      public new static readonly IsNaNOp Instance = new IsNaNOp();
      private IsNaNOp() { }
      public override string Name { get { return "IsNaN"; } }
      public override Func<Expr<double>, Expr<bool>> Uniform { get { return DoubleBl.IsNaNOp.Instance.Bl(); } }
    }
    public class IsInfinityOp : IsOp<IsInfinityOp>, ICustomShaderCallOperator {
      public new static readonly IsInfinityOp Instance = new IsInfinityOp();
      private IsInfinityOp() { }
      public override string Name { get { return "IsInfinity"; } }
      public string ShaderName { get { return "isinf"; } }
      public override Func<Expr<double>, Expr<bool>> Uniform { get { return DoubleBl.IsInfinityOp.Instance.Bl(); } }
    }
    public class IsFiniteOp : IsOp<IsFiniteOp>, INoLinqOperator {
      public new static readonly IsFiniteOp Instance = new IsFiniteOp();
      private IsFiniteOp() { }
      public override string Name { get { return "IsFinite"; } }
      public override Func<Expr<double>, Expr<bool>> Uniform { get { return DoubleBl.IsFiniteOp.Instance.Bl(); } }
      public override Expr<bool> Expand(Expr<IVec<double, D>> argA) {
        var ArgA = ToBrandD(argA);
        return !ArgA.IsInfinity;
      }
    }
    public class IsPositiveInfinityOp : IsOp<IsPositiveInfinityOp>, INoShaderOperator {
      public new static readonly IsPositiveInfinityOp Instance = new IsPositiveInfinityOp();
      private IsPositiveInfinityOp() { }
      public override string Name { get { return "IsPositiveInfinity"; } }
      public override Func<Expr<double>, Expr<bool>> Uniform { get { return DoubleBl.IsPositiveInfinityOp.Instance.Bl(); } }
      public override Expr<bool> Expand(Expr<IVec<double, D>> argA) {
        var ArgA = ToBrandD(argA);
        return ArgA.IsInfinity & ArgA > Repeat(0d);
      }
    }
    public class IsNegativeInfinityOp : IsOp<IsNegativeInfinityOp>, INoShaderOperator {
      public new static readonly IsNegativeInfinityOp Instance = new IsNegativeInfinityOp();
      private IsNegativeInfinityOp() { }
      public override string Name { get { return "IsNegativeInfinity"; } }
      public override Func<Expr<double>, Expr<bool>> Uniform { get { return DoubleBl.IsNegativeInfinityOp.Instance.Bl(); } }
      public override Expr<bool> Expand(Expr<IVec<double, D>> argA) {
        var ArgA = ToBrandD(argA);
        return ArgA.IsInfinity & ArgA < Repeat(0d);
      }
    }
    public virtual FlexIntBl<D> Sign {
      get {
        return SignOp.Instance.Make(UnderlyingD);
      }
    }
    public virtual FlexDoubleBl<D> SafeSign { 
      get {
        return IsNaN.Condition((FlexDoubleBl<D>) double.NaN, Sign);
      } 
    }
    public static implicit operator FlexDoubleBl<D>(DoubleBl<T, BRAND, D> Self) { return Self.UnderlyingD; }

    public BRAND RoundN(BRAND By) {
      return (this * By).Round / By;
    }
    public BRAND RoundM(BRAND By) {
      return (this / By).Round * By;
    }

    public virtual BRAND Saturate { get { return ToBrandD(SaturateOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Floor { get { return ToBrandD(FloorOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Ceiling { get { return ToBrandD(CeilingOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Round { get { return ToBrandD(RoundOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Exp { get { return ToBrandD(ExpOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Log { get { return ToBrandD(LogOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Exp2 { get { return ToBrandD(Exp2Op.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Log2 { get { return ToBrandD(Log2Op.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Exp10 { get { return ToBrandD(Exp10Op.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Log10 { get { return ToBrandD(Log10Op.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Pow(BRAND Power) {
      if (Power.Equals(Zero)) return One;
      else if (Power.Equals(One)) return this;
      else return ToBrandD(PowOp.Instance.Make(UnderlyingD, Power.UnderlyingD)); 
    }
    public virtual BRAND Pow(double Power) { return ToBrandD(PowOp.Instance.Make(UnderlyingD, Repeat(Power).UnderlyingD)); }
    public virtual BRAND LogN(BRAND Base) { return ToBrandD(LogNOp.Instance.Make(UnderlyingD, Base.UnderlyingD)); }

    public virtual BRAND Recip { get { return ToBrandD(RecipOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Square { get { return ToBrandD(SquareOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Sqrt { get { return ToBrandD(SqrtOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Rsqrt { get { return ToBrandD(RsqrtOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Frac { get { return ToBrandD(FracOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Ldexp(BRAND other) { return ToBrandD(LdexpOp.Instance.Make(UnderlyingD, other.UnderlyingD)); }

    public virtual BRAND Ddx { get { return ToBrandD(DdxOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Ddy { get { return ToBrandD(DdyOp.Instance.Make(UnderlyingD)); } }
    public virtual BRAND Fwidth { get { return ToBrandD(FwidthOp.Instance.Make(UnderlyingD)); } }

    public virtual DoubleBl Dot(BRAND Other) { return (DotOp.Instance.Make(UnderlyingD, Other.UnderlyingD)); }
    public virtual DoubleBl LengthSquared { get { return IsNormalized ? 1d.Bl() : (DoubleBl) LengthSquaredOp.Instance.Make(UnderlyingD); } }
    public virtual DoubleBl Length { get { return IsNormalized ? 1d.Bl() : (DoubleBl) LengthOp.Instance.Make(UnderlyingD); } }
    public virtual DoubleBl Distance(BRAND Other) { return (DistanceOp.Instance.Make(UnderlyingD, Other.UnderlyingD)); }

    public bool IsNormalized { get; protected set; }

    public override BRAND CopyMetaTo(BRAND Other) {
      Other = base.CopyMetaTo(Other);
      Other.IsNormalized = this.IsNormalized;
      return Other;
    }

    public BRAND VerifyNormalized {
      get {
        this.IsNormalized = true;
        // ensure normalized
        // var OldF = this.AsRHS0;
        // this.AsRHS0 = (value) => OldF(value).Normalize;

        var OldVerifyRhs = this.VerifyRHS;
        this.VerifyRHS = (value) => value.IsNormalized && OldVerifyRhs(value);
        this.RHSFail += "; not normalized";
        return (BRAND)this;
      }
    }
    /*
    public BRAND MakeNormalized {
      get {
        this.IsNormalized = true;
        // ensure normalized
        var OldF = this.AsRHS0;
        this.AsRHS0 = (value) => OldF(value).RawNormalize;
        return (BRAND)this;
      }
    }*/

    public override BRAND ChooseA(BoolBl Test, BRAND Other) {
      var ret = base.ChooseA(Test, Other);
      ret.IsNormalized = IsNormalized && Other.IsNormalized;
      return ret;
    }
    public virtual BRAND Normalize {
      get {
        if (IsNormalized) return this;
        var ret = ToBrandD(SafeNormalizeOp.Instance.Make(UnderlyingD));
        ret.IsNormalized = true;
        return ret;
      }
    }

    public virtual BRAND RawNormalize {
      get {
        if (IsNormalized) return this;
        var ret = ToBrandD(NormalizeOp.Instance.Make(UnderlyingD));
        ret.IsNormalized = true;
        return ret;
      }
    }

    public virtual BoolBl IsInfinity { get { return IsInfinityOp.Instance.Make(UnderlyingD); } }
    public virtual BoolBl IsFinite { get { return IsFiniteOp.Instance.Make(UnderlyingD); } }
    public virtual BoolBl IsNaN { get { return IsNaNOp.Instance.Make(UnderlyingD); } }
    public virtual BoolBl IsPositiveInfinity { get { return IsPositiveInfinityOp.Instance.Make(UnderlyingD); } }
    public virtual BoolBl IsNegativeInfinity { get { return IsNegativeInfinityOp.Instance.Make(UnderlyingD); } }

    public BRAND Snap(BRAND By, BRAND Delta) {
      var ret = new DoubleBl[Dim<D>.Count];
      for (int i = 0; i < ret.Length; i++) {
        var p0 = this[i] % By[i];
        p0 = (p0 < Delta[i]).Condition(-p0, (p0 > By[i] - Delta[i]).Condition(By[i] - p0, 0d));
        ret[i] = this[i] + p0;
      }
      var flex = new FlexDoubleBl<D>(ret);
      return ToBrandD(flex.UnderlyingD);
      
    }



    public static readonly BRAND Unit;
    public static readonly BRAND Zero;
    public static readonly BRAND One;
    static DoubleBl() {
      {
        Expr<double>[] Es = new Expr<double>[Dim<D>.Count];
        Es[0] = ((DoubleBl)1d);
        for (int i = 1; i < Dim<D>.Count; i++) Es[i] = ((DoubleBl)0d);
        Unit = ToBrandD(Composite<double, D>.Make(Es)).VerifyNormalized;
      }
      {
        Zero = Repeat(0d);
        One = Repeat(1d);
      }
    }
    public override BRAND Multiply(BRAND OpB) {
      if (this.Provider.Equals(Zero.Provider)) return Zero;
      if (OpB.Provider.Equals(Zero.Provider)) return Zero;
      if (this.Provider.Equals(One.Provider)) return OpB;
      if (OpB.Provider.Equals(One.Provider)) return this;
      return base.Multiply(OpB);
    }
    public override BRAND Divide(BRAND OpB) {
      if (this.Provider.Equals(Zero.Provider)) return Zero;
      if (OpB.Provider.Equals(One.Provider)) return this;
      return base.Divide(OpB);
    }
    public override BRAND Add(BRAND OpB) {
      if (this.Provider.Equals(Zero.Provider)) return OpB;
      if (OpB.Provider.Equals(Zero.Provider)) return this;
      return base.Add(OpB);
    }
    public override BRAND Subtract(BRAND OpB) {
      if (this.Provider.Equals(Zero.Provider)) return OpB.Negate;
      if (OpB.Provider.Equals(Zero.Provider)) return this;
      return base.Subtract(OpB);
    }
  }
  public abstract partial class RealDoubleBl<T, BRAND, D> : DoubleBl<T, BRAND, D>
    where BRAND : RealDoubleBl<T, BRAND, D>
    where D : Dim<D> {
    public RealDoubleBl(Expr<T> Underlying) : base(Underlying) { }
    public RealDoubleBl(Expr<IVec<double, D>> Underlying) : base(Underlying) { }
    public RealDoubleBl(DoubleBl[] Es) : base(Es) { }
    public RealDoubleBl() : base() { }
  }


  public abstract partial class BaseDoubleBl : RealDoubleBl<double, DoubleBl, D1> {
    public BaseDoubleBl(Expr<double> Underlying) : base(Underlying) { }
    public BaseDoubleBl(Expr<IVec<double, D1>> Underlying) : base(Underlying) { }
    public BaseDoubleBl(DoubleBl[] Es) : base(Es) { }
    public BaseDoubleBl() : base() { }
    public Double2Bl AddX(DoubleBl X) { return new Double2Bl(X, this); }
    public Double2Bl AddY(DoubleBl Y) { return new Double2Bl(this, Y); }
    public BRAND Interpolate<BRAND>(ICanInterpolate<BRAND> From, BRAND To) where BRAND : ICanInterpolate<BRAND> {
      return From.CoreInterpolate((BRAND) From, To, this);
    }
    public DoubleBl Interpolate(double from, double to) {
      return this.Interpolate(from.Bl(), to.Bl());
    }
    public DoubleBl Interpolate(int from, int to) {
      return this.Interpolate((DoubleBl) from.Bl(), (DoubleBl) to.Bl());
    }
  }


  /// <summary>
  /// Basic 1D double for measuring distance, progress, deltas, and so on. 
  /// </summary>
  public partial class DoubleBl : BaseDoubleBl,ICoreBrandT {
    public DoubleBl(Expr<double> Underlying) : base(Underlying) { }
    public DoubleBl(Expr<IVec<double, D1>> Underlying) : base(Underlying) { }
    public DoubleBl(DoubleBl[] Es) : base(Es) { }
    public DoubleBl() : base() { }

    public BRAND Interpolate<BRAND>(BRAND From, ICanInterpolate<BRAND> To) where BRAND : ICanInterpolate<BRAND> {
      return From.CoreInterpolate(From, (BRAND) To, this);
    }
    public BRAND Lerp<BRAND>(BRAND From, ICanInterpolate<BRAND> To) where BRAND : ICanInterpolate<BRAND> {
      return Interpolate(From, To);
    }
    public DoubleBl Lerp<BRAND>(double From, double To) {
      return Interpolate(From.Bl(), To.Bl());
    }

    public static implicit operator DoubleBl(FlexDoubleBl<D1> v) { return new DoubleBl(v.Provider); }
    public static implicit operator DoubleBl(FlexIntBl<D1> v) { return (FlexDoubleBl<D1>) v; }
    public static implicit operator DoubleBl(FlexBl<double, D1, DoubleBl> v) { return new DoubleBl(v.Provider); }
    public static implicit operator DoubleBl(Expr<double> E) { return new DoubleBl(E); }
    public static implicit operator DoubleBl(double d) { return new Constant<double>(d); }
    public static implicit operator DoubleBl(int d) { return (IntBl) d; }
    public static implicit operator DoubleBl(Random r) {
      Repeat(0d);
      return r.NextDouble(); }
  }
  public abstract partial class DoubleBl<D, BRAND> : RealDoubleBl<IVec<double, D>, BRAND, D>
    where D : Dim<D>
    where BRAND : DoubleBl<D, BRAND> {
    public DoubleBl(Expr<IVec<double, D>> Underlying) : base(Underlying) { }
    public DoubleBl(DoubleBl[] Es) : base(Es) { }
    public DoubleBl() : base() { }
  }
  // Flexible, can represent double vectors for any D, even D0!
  public partial class FlexDoubleBl<D> : DoubleBl<D, FlexDoubleBl<D>> where D : Dim<D> {
    public FlexDoubleBl(Expr<IVec<double, D>> Underlying) : base(Underlying) { }
    public FlexDoubleBl(params DoubleBl[] Es) : base(Es) { }
    public FlexDoubleBl() : base() { }

    public static implicit operator FlexDoubleBl<D>(Expr<IVec<double, D>> e) { return new FlexDoubleBl<D>(e); }
    public static implicit operator FlexDoubleBl<D>(FlexDoubleBl<D1> u) { return Repeat(u); }
    public static implicit operator FlexDoubleBl<D>(double u) { return Repeat(u); }
    public static implicit operator FlexDoubleBl<D>(DoubleBl u) { return Repeat(u); }
    public static implicit operator FlexBl<double, D, DoubleBl>(FlexDoubleBl<D> u) {
      return new FlexBl<double, D, DoubleBl>(u.Provider);
    }
    public static implicit operator FlexDoubleBl<D>(FlexBl<double, D, DoubleBl> u) {
      return new FlexDoubleBl<D>(u.Provider);
    }
  }
  public abstract partial class FixDoubleBl<D, BRAND> : DoubleBl<D, BRAND>, ICoreBrandT
    where D : Dim1D<D>
    where BRAND : FixDoubleBl<D, BRAND> {
    public FixDoubleBl(Expr<IVec<double, D>> Underlying) : base(Underlying) { }
    public FixDoubleBl(params DoubleBl[] Es) : base(Es) { }
    public FixDoubleBl() : base() { }
  }

  public partial class Double1Bl : FixDoubleBl<D1, Double1Bl> {
    public Double1Bl(Expr<IVec<double, D1>> Underlying) : base(Underlying) { }
    public Double1Bl(DoubleBl X) : base(X) { }
    public Double1Bl() : base() { }
    public static implicit operator Double1Bl(FlexDoubleBl<D1> v) { return v.UnderlyingD; }
    public static implicit operator Double1Bl(FlexIntBl<D1> v) { return (FlexDoubleBl<D1>)v; }
    public static implicit operator Double1Bl(IntBl<D1> v) { return (FlexIntBl<D1>)v; }

    public static implicit operator FlexDoubleBl<D1>(Double1Bl v) { return new FlexDoubleBl<D1>(v.Provider); }
    public static implicit operator Double1Bl(FlexBl<double, D1, DoubleBl> v) { return new Double1Bl(v.Provider); }
    public static implicit operator FlexBl<double, D1, DoubleBl>(Double1Bl v) { return new FlexDoubleBl<D1>(v.Provider); }

    public static implicit operator Double1Bl(DoubleBl d) { return d; }
    public static implicit operator Double1Bl(IntBl d) { return (DoubleBl)d; }
    public static implicit operator Double1Bl(double d) { return (DoubleBl)d; }
    public static implicit operator Double1Bl(int d) { return (DoubleBl)d; }

    public static implicit operator Double1Bl(Expr<IVec<double, D1>> E) { return new Double1Bl(E); }
  }

  public abstract partial class PointDoubleBl<D, BRAND> : FixDoubleBl<D, BRAND>
    where D : Dim1D<D>
    where BRAND : PointDoubleBl<D, BRAND> {
    public PointDoubleBl(Expr<IVec<double, D>> Underlying) : base(Underlying) { }
    public PointDoubleBl(params DoubleBl[] Es) : base(Es) { }
    public PointDoubleBl() : base() { }
  }


  public partial class Double2Bl : PointDoubleBl<D2, Double2Bl>, IHasXY<double, DoubleBl> {
    public Double2Bl(Expr<IVec<double, D2>> Underlying) : base(Underlying) { }
    public Double2Bl(DoubleBl X, DoubleBl Y) : base(X, Y) { }
    public Double2Bl() : base() { }
    public static implicit operator Double2Bl(FlexDoubleBl<D2> v) { return new Double2Bl(v.Provider); }
    public static implicit operator Double2Bl(FlexDoubleBl<D1> v) { return v.Bl(); }
    public static implicit operator Double2Bl(FlexIntBl<D2> v) { return (FlexDoubleBl<D2>)v; }
    public static implicit operator Double2Bl(FlexIntBl<D1> v) { return Repeat(v[0]); }
    public static implicit operator Double2Bl(IntBl<D2> v) { return (FlexIntBl<D2>)v; }
    public static implicit operator Double2Bl(Random r) { return new Double2Bl(r.NextDouble(), r.NextDouble()); }

    public static implicit operator FlexDoubleBl<D2>(Double2Bl v) { return new FlexDoubleBl<D2>(v.Provider); }
    public static implicit operator Double2Bl(FlexBl<double,D2,DoubleBl> v) { return new Double2Bl(v.Provider); }
    public static implicit operator FlexBl<double, D2, DoubleBl>(Double2Bl v) { return new FlexDoubleBl<D2>(v.Provider); }

    public static implicit operator Double2Bl(DoubleBl d) { return d.XX(); }
    public static implicit operator Double2Bl(IntBl d) { return (DoubleBl)d; }
    public static implicit operator Double2Bl(double d) { return (DoubleBl)d; }
    public static implicit operator Double2Bl(int d) { return (DoubleBl)d; }

    public static implicit operator Double2Bl(Expr<IVec<double, D2>> E) { return new Double2Bl(E); }
    public Double2Bl MapX(Func<DoubleBl, DoubleBl> F) { return new Double2Bl(F(X), Y); }
    public Double2Bl MapY(Func<DoubleBl, DoubleBl> F) { return new Double2Bl((X), F(Y)); }

    public Double3Bl AddX(DoubleBl X) { return new Double3Bl(X, this); }
    public Double3Bl AddY(DoubleBl Y) { return new Double3Bl(this.X, Y, this.Y); }
    public Double3Bl AddZ(DoubleBl Z) { return new Double3Bl(this, Z); }
  }
  public partial class Double3Bl : PointDoubleBl<D3, Double3Bl>, IHasXYZ<double, DoubleBl> {
    public Double3Bl(Expr<IVec<double, D3>> Underlying) : base(Underlying) { }
    public Double3Bl(DoubleBl X, DoubleBl Y, DoubleBl Z) : base(X, Y, Z) { }
    public Double3Bl(Double2Bl XY, DoubleBl Z) : base(CombineOp<D2,D1>.Instance.Make(XY,Z)) { }
    public Double3Bl(DoubleBl X, Double2Bl YZ) : base(CombineOp<D1, D2>.Instance.Make(X, YZ)) { }
    public Double3Bl() : base() { }
    public static implicit operator Double3Bl(FlexDoubleBl<D3> v) { return new Double3Bl(v.Provider); }
    public static implicit operator Double3Bl(FlexDoubleBl<D1> v) { return v.Bl(); }
    public static implicit operator Double3Bl(FlexIntBl<D3> v) { return (FlexDoubleBl<D3>)v; }
    public static implicit operator Double3Bl(FlexIntBl<D1> v) { return Repeat(v[0]); }
    public static implicit operator Double3Bl(IntBl<D3> v) { return (FlexIntBl<D3>)v; }

    public static implicit operator FlexDoubleBl<D3>(Double3Bl v) { return new FlexDoubleBl<D3>(v.Provider); }
    public static implicit operator Double3Bl(FlexBl<double, D3, DoubleBl> v) { return new Double3Bl(v.Provider); }


    public static implicit operator FlexBl<double, D3, DoubleBl>(Double3Bl v) { return new FlexDoubleBl<D3>(v.Provider); }

    public static implicit operator Double3Bl(DoubleBl d) { return d.XXX(); }
    public static implicit operator Double3Bl(IntBl d) { return (DoubleBl)d; }
    public static implicit operator Double3Bl(double d) { return (DoubleBl)d; }
    public static implicit operator Double3Bl(int d) { return (DoubleBl)d; }

    public static implicit operator Double3Bl(Expr<IVec<double, D3>> E) { return new Double3Bl(E); }

    public Double4Bl AddX(DoubleBl X) { return new Double4Bl(X, this); }
    public Double4Bl AddY(DoubleBl Y) { return new Double4Bl(this.X.AddY(Y), this.YZ()); }
    public Double4Bl AddZ(DoubleBl Z) { return new Double4Bl(this.XY(), this.Z.AddX(Z)); }
    public Double4Bl AddW(DoubleBl W) { return new Double4Bl(this, W); }

    public Double3Bl Cross(Double3Bl Other) { return CrossOp.Instance.Make(this, Other); }

    public partial class CrossOp : CallBinaryOp<CrossOp>, INoLinqOperator {
      public new static readonly CrossOp Instance = new CrossOp();
      private CrossOp() { }
      public override string Name { get { return "Cross"; } }
      public override Func<Expr<double>, Expr<double>, Expr<double>> Uniform {
        get { return null; }
      }
      protected override Expr<IVec<double, D3>> Expand0(Expr<IVec<double, D3>> argA, Expr<IVec<double, D3>> argB) {
        Double3Bl a = argA;
        Double3Bl b = argB;
        // a × b = (a2b3 − a3b2, a3b1 − a1b3, a1b2 − a2b1).
        var result = new Double3Bl(
          // a2b3 − a3b2
          a[1] * b[2] - a[2] * b[1],
          // a3b1 − a1b3
          a[2] * b[0] - a[0] * b[2],
          // a1b2 − a2b1
          a[0] * b[1] - a[1] * b[0]);
        return result;
      }
    }


  }
  public partial class Double4Bl : FixDoubleBl<D4, Double4Bl>, IHasXYZW<double,DoubleBl> {
    public Double4Bl(Expr<IVec<double, D4>> Underlying) : base(Underlying) { }
    public Double4Bl(DoubleBl X, DoubleBl Y, DoubleBl Z, DoubleBl W) : base(X, Y, Z, W) { }


    public Double4Bl(Double3Bl XYZ, DoubleBl W) : base(CombineOp<D3,D1>.Instance.Make(XYZ,W)) { }
    public Double4Bl(DoubleBl X, Double3Bl YZW) : base(CombineOp<D1, D3>.Instance.Make(X, YZW)) { }
    public Double4Bl(Double2Bl XY, Double2Bl ZW) : base(CombineOp<D2, D2>.Instance.Make(XY, ZW)) { }
    public Double4Bl() : base() { }

    public static implicit operator Double4Bl(FlexDoubleBl<D4> v) { return new Double4Bl(v.Provider); }
    public static implicit operator Double4Bl(FlexDoubleBl<D1> v) { return v.Bl(); }
    public static implicit operator Double4Bl(FlexIntBl<D4> v) { return (FlexDoubleBl<D4>)v; }
    public static implicit operator Double4Bl(FlexIntBl<D1> v) { return Repeat(v[0]); }
    public static implicit operator Double4Bl(IntBl<D4> v) { return (FlexIntBl<D4>)v; }

    public static implicit operator FlexDoubleBl<D4>(Double4Bl v) { return new FlexDoubleBl<D4>(v.Provider); }
    public static implicit operator Double4Bl(FlexBl<double, D4, DoubleBl> v) { return new Double4Bl(v.Provider); }
    public static implicit operator FlexBl<double, D4, DoubleBl>(Double4Bl v) { return new FlexDoubleBl<D4>(v.Provider); }

    public static implicit operator Double4Bl(DoubleBl d) { return d.XXXX(); }
    public static implicit operator Double4Bl(IntBl d) { return (DoubleBl)d; }
    public static implicit operator Double4Bl(double d) { return (DoubleBl)d; }
    public static implicit operator Double4Bl(int d) { return (DoubleBl)d; }
    public static implicit operator Double4Bl(Expr<IVec<double, D4>> E) { return new Double4Bl(E); }

  }
}
namespace Bling.Core {
  using Bling.Matrices;
  public static partial class BrandExtensions {


    public static DoubleBl Bl(this Expr<double> Value) { return Value; }
    public static DoubleBl Bl(this double Value) { return Value; }
    public static DoubleBl Bl(this FlexDoubleBl<D1> Value) { return Value; }

    public static SCALAR Bl<K,SCALAR>(this FlexBl<K,D1,SCALAR> Value) where SCALAR : ValueBrand<K,SCALAR,K,D1,SCALAR> { return Value[0]; }

    public static Double2Bl Bl(this Expr<IVec<double,D2>> Value) { return Value; }
    public static Double2Bl Bl(this IVec<double, D2> Value) { return new Constant<IVec<double,D2>>(Value); }
    public static Double2Bl Bl(this FlexDoubleBl<D2> Value) { return Value; }
    public static Double2Bl Bl(this FlexBl<double,D2,DoubleBl> Value) { return Value; }

    public static Double3Bl Bl(this Expr<IVec<double, D3>> Value) { return Value; }
    public static Double3Bl Bl(this IVec<double, D3> Value) { return new Constant<IVec<double, D3>>(Value); }
    public static Double3Bl Bl(this FlexDoubleBl<D3> Value) { return Value; }
    public static Double3Bl Bl(this FlexBl<double, D3, DoubleBl> Value) { return Value; }

    public static Double4Bl Bl(this Expr<IVec<double, D4>> Value) { return Value; }
    public static Double4Bl Bl(this IVec<double, D4> Value) { return new Constant<IVec<double, D4>>(Value); }
    public static Double4Bl Bl(this FlexDoubleBl<D4> Value) { return Value; }
    public static Double4Bl Bl(this FlexBl<double, D4, DoubleBl> Value) { return Value; }

    public static BoolBl Bl(this Expr<bool> Value) { return Value; }
    public static BoolBl Bl(this bool Value) { return Value; }
    public static BoolBl Bl<D>(this FlexBoolBl<D> Value) where D : Dim<D> { return Value; }
    public static BoolBl<D> Cl<D>(this FlexBoolBl<D> Value) where D : Dim1D<D>, IMultiDim1D<D> { return Value; }

    public static IntBl Bl(this Expr<int> Value) { return Value; }
    public static IntBl Bl(this int Value) { return Value; }
    public static IntBl Bl(this IntBl<D1> Value) { return Value; }

    public static Matrix2Bl Bl(this MatrixBl<D2, D2> Value) { return Value; }
    public static Matrix3Bl Bl(this MatrixBl<D3, D3> Value) { return Value; }
    public static Matrix4Bl Bl(this MatrixBl<D4, D4> Value) { return Value; }


    public static Func<Expr<A>, Expr<C>> Bl<A, C>(this Func<Expr<IVec<A,D1>>, Expr<IVec<C, D1>>> F) {
      return (a) => AccessExpr<C,D1>.Make(F(Composite<A,D1>.Make(a)), 0);
    }
    public static Func<Expr<A>, Expr<C>> Bl<A, C>(this Func<Expr<IVec<A, D1>>, Expr<C>> F) {
      return (a) => F(Composite<A, D1>.Make(a));
    }
    public static Func<Expr<A>, Expr<B>, Expr<C>> Bl<A, B, C>(this Func<Expr<IVec<A, D1>>, Expr<IVec<B, D1>>, Expr<IVec<C, D1>>> F) {
      return (a, b) => AccessExpr<C, D1>.Make(F(Composite<A, D1>.Make(a), Composite<B, D1>.Make(b)), 0);
    }
    public static Func<Expr<A>, Expr<B>, Expr<C>, Expr<D>> Bl<A, B, C, D>(this Func<Expr<IVec<A, D1>>, Expr<IVec<B, D1>>, Expr<IVec<C, D1>>, Expr<IVec<D, D1>>> F) {
      return (a, b, c) => AccessExpr<D, D1>.Make(F(Composite<A, D1>.Make(a), Composite<B, D1>.Make(b), Composite<C, D1>.Make(c)), 0);
    }
    public static Func<Expr<A>, Expr<C>> Bl<A, C>(this Ops.IOperatorX<IVec<A, D1>, IVec<C, D1>> F) {
      Func<Expr<IVec<A,D1>>, Expr<IVec<C, D1>>> G = F.Make;
      return G.Bl();
    }
    public static Func<Expr<A>, Expr<B>, Expr<C>> Bl<A, B, C>(this Ops.OperatorX<IVec<A, D1>, IVec<B, D1>, IVec<C, D1>> F) {
      Func<Expr<IVec<A, D1>>, Expr<IVec<B, D1>>, Expr<IVec<C, D1>>> G = F.Make;
      return G.Bl();
    }
    public static Func<Expr<A>, Expr<B>, Expr<C>, Expr<D>> Bl<A, B, C, D>(this Ops.OperatorX<IVec<A, D1>, IVec<B, D1>, IVec<C, D1>, IVec<D, D1>> F) {
      Func<Expr<IVec<A, D1>>, Expr<IVec<B, D1>>, Expr<IVec<C, D1>>, Expr<IVec<D, D1>>> G = F.Make;
      return G.Bl();
    }
    public static Func<Expr<A>, Expr<C>> Bl<A, C>(this Ops.IOperatorX<IVec<A, D1>, C> F) {
      Func<Expr<IVec<A, D1>>, Expr<C>> G = F.Make;
      return G.Bl();
    }
    public static BRAND Condition<BRAND>(this bool b, IValueBrand<BRAND> ArgA, BRAND ArgB) where BRAND : IValueBrand<BRAND> {
      return b ? (BRAND) ArgA : ArgB;
    }
    /// <summary>
    /// Table array into a branded value based on branded integer index.
    /// </summary>
    public static BRAND Table<BRAND>(this BRAND[] Values, IntBl Index) where BRAND : ICanTable<BRAND> {
      Index = Index.Provider.Fold;
      if (Index.Provider.IsObviousConstant)
        return Values[Index.CurrentValue];
      return Values[0].Table(Index.Provider, Values);
    }

  }

}